Перші кроки
Дані користувача
- Огляд адаптивного email-редактора
- Cтворення оформлення для листа
- Створення синхронізованих модулів
- Налаштування адаптивності
- Налаштування smart-контейнерів
- Оформлення промовкладки для Gmail
- Додавання Ролловера
- Додавання анкорних посилань
- Бібліотека модулів
- Додавання таблиці до листа
- Додавання кастомних шрифтів
- Створення кнопки СТA
- Робота з блоком "Зображення"
- Робота з блоком “Таймер"
- Використання ШІ в email-редакторі
- Підтримка месенджер-протоколів поштовими клієнтами та платформами
Омніканальність
- SDK для мобільних застосунків
- Керування ключами доступу до мобільного SDK
- Підключення мобільного застосунку
- Створення та завантаження ключа Firebase
- Створення мобільних push-повідомлень
- Налаштування аналітики доставлень та кліків
- Планування мобільних push-повідомлень
- Типи діплінків
- Надсилання тестових повідомлень із налагодження запитів
- Налаштування віджетів для сайту
- Гейміфікація віджетів
- Виклик віджета
- Налаштування геоданих для правил виклику віджетів
- Збереження даних із віджетів у поля контактів
- Захист від роздратування
- Дії після підписки
- Заміна системного сценарію Double Opt-In
- Створення pop-up-форм за допомогою Google Tag Manager або WordPress
- Надсилання подій з віджетів eSputnik до Google Analytics
- A/B-тестування віджетів
- Збір контактних даних за допомогою форм запитів
Автоматизація
- Налаштування та редагування сценаріїв
- Налаштування умов запуску та зупинки сценарію
- Блок “Старт”
- Група блоків “Популярні”
- Група блоків “Повідомлення”
- Використання блока повідомлень “Одне з багатьох”
- Група блоків “Контакт”
- Група блоків "Умови"
- Група блоків “Інше”
- Група блоків “Повідомлення на групу”
- Група блоків “Час”
- Розширені параметри блоків сценаріїв
- Дозволений час відправлення
- Вебхуки в сценаріях
- Відстеження історії запусків сценарію
- Якщо сценарій не працює
- Подвійне підтвердження підписки
- Вітальна серія
- Вітальна серія із сегментацією за категоріями
- Запуск сценарію після імпорту контактів
- Регулярний сценарій для групи
- Вітання з днем народження
- Привʼязка сценарію до кнопки
- Використання змінних із замовлення у сценарії
- Збір відгуків про замовлення
- Реактивація клієнтів та підписників
- Відправка розсилки непрочитавшим
- Налаштування додаткових розсилок
- Відправлення нагадувань в заданий користувачем час
- А/B-тестування в сценаріях
Персоналізація
- Підстановка промокоду з файлу
- Підстановка промокоду з використанням API
- Принципи генерації промокодів за допомогою PHP/JAVA
- Підстановка промокоду за допомогою персоналізації
- Завантаження промокодів для використання в сценарії
- Генерація промокодів у сценарії
- Відправлення промокоду за допомогою передпроцесора
- HTTP-запит для передачі промокоду з повідомлення до картки контакту
Аналітика
- Звіт щодо email-розсилки
- Звіт щодо SMS-розсилки
- Звіт щодо розсилки Web Push
- Звіт щодо Viber-розсилки
- Звіт щодо розсилки Mob Push
- Звіт щодо розсилки App Inbox
- Звіт щодо Telegram-розсилки
- Звіт зі взаємодії з In-App
- Звіт зі взаємодії з віджетами
- Звіт щодо тригерної розсилки
- Звіт щодо AMP-розсилки
- Звіт щодо мультимовної розсилки
- Налаштування передачі UTM-міток
- Візуалізація доходу
- Відстеження ефективності кампаній у Google Analytics 4
- Статистика повідомлень
Мультимовність
Відстеження подій та поведінки
- Події для запуску тригерних розсилок
- Найменування користувацьких подій
- Валідація параметрів подій
- Відстеження активності на сайті за допомогою Generate event
- Підстановка даних з подій в повідомлення
- Розгалуження сценарію в залежності від параметрів події
- Відстеження активності клієнтів у мобільних застосунках
- Вебхуки для відстеження активності
- Аналітика подій
Товарні рекомендації
API
- Поширені питання: Інтеграція з API
- API-ключі
- Ресурси API для додавання контактів
- Використання API-ресурсу Generate event
- Передача замовлень API-ресурсом Generate event
- Отримання рекомендацій щодо API ресурсом Contact recommendations based on web tracking
- Використання API-ресурсу Send prepared message
Зміна системи
Документи
Інтеграція
Принципи генерації промокодів за допомогою PHP/JAVA
Якщо загальні методи підстановки промокодів вам не підходять, розгляньте можливість реалізації цього завдання за допомогою PHP/JAVA.
Формат промокоду, який підтримує eSputnik
Промокод містить дату, до якої він діє, тип акції, розмір знижки та контрольну суму.
У результаті отримаємо такий рядок:
<YY><MM><DD><Promo type><Discount><CRC>
Поле Довжина Опис Приклад YY 2 символи Рік, двозначне число 15, 54 MM 2 символи Місяць, двозначне число, якщо треба, доповнюється зліва нулем 01, 12 DD 2 символи День, двозначне число, якщо треба, доповнюється зліва нулем 06, 28 Promo type 1 символ Тип промокоду, може набувати значення від 0 до 31, кодується символом з алфавіту Base32 A, D, X Discount 2 символи Розмір знижки у %, двозначне число, якщо треба, доповнюється нулем зліва 15, 02 CRC 1 символ Контрольна сума – одне зі значень алфавіту Base32 B, N, Z У результаті виходить рядок завдовжки 10 символів такого виду: 151231Y16N
Зверніть увагу
Значення промокодів залежить від параметрів блоку та поточного календарного числа. Тобто протягом доби всі контакти отримуватимуть однаковий промокод, якщо у параметри блоку не вноситимуться зміни. Відстеження використання промокоду та терміну його дії має відбуватись на вашому боці.
Приклад використання типу промокоду (Promo type)
- 0 – діє для всього кошика (must-have)
- 1 – діє лише для категорії А
- 2 – діє лише для категорії В
Важливо!
Якщо ви хочете використовувати типи промокоду таким чином, надішліть файл у підтримку eSputnik, вказавши, яка категорія продукту відповідає тому чи іншому коду.
Алгоритм розрахунку контрольної суми (CRC)
- По порядку сумується десяткове ASCII-значення кожного символу у вихідному рядку.
- Отримана сума ділиться із залишком на 32.
- Отриманий залишок використовується як індекс символу в алфавіті Base32.
Символ цього індекса і буде контрольною сумою.
Приклад коду на java:
public static final String BASE32_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; public char checkSum(String data) { int sum = 0; for (char c : data.toCharArray()) { sum += c; } return BASE32_ALPHABET.charAt(sum % BASE32_ALPHABET.length()); }
Кодування/декодування промокоду
Для кодування/декодування використовується симетричний алгоритм шифрування Triple DES.
Щоб отримати людиночитаний текст, отримані під час шифрування дані кодуються за допомогою Base32.
Параметри шифрування, що використовуються:
- ключ довжиною 24 байти,
- initialization vector довжиною 8 байтів,
- режим шифрування: CFB8 (Cipher Feedback Mode),
- доповнення: NoPadding.
Послідовність дій під час кодування промокоду
- До промокоду застосовується алгоритм шифрування Triple DES.
- Щоб отримати людиночитаний текст, отримані за допомогою шифрування дані кодуються за допомогою Base32.
- Через кожні 4 символи для читабельності додається “-”.
Послідовність дій при декодуванні промокоду
- Видаліть “-”.
- Спочатку дані декодуються за допомогою Base32.
- Далі декодовані дані розшифровуються за допомогою Triple DES.
- Має вийти рядок із 10 символів згідно з описаним вище форматом. Для контролю правильності розшифрування використовується контрольна сума.
Секретний ключ
Для кодування та декодування промокодів секретний ключ використовується на стороні eSputnik і на стороні сервісу, який перевіряє промокоди.
Згенеруйте ключ eSSuperKeyXXXXXXXXXXXXXX (де XXX… – випадкові цифри) та створіть вектор ініціалізації: 12345678.
Важливо
Вектор ініціалізації завжди має бути 12345678.
Передайте обидва ці значення в підтримку eSputnik.
Приклад Java-коду
package promocode;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import org.apache.commons.codec.binary.Base32;
public class CryptData {
private KeySpec keySpec;
private SecretKey key;
private IvParameterSpec iv;
public CryptData(String keyString, String ivString) {
try {
keySpec = new DESedeKeySpec(keyString.getBytes("UTF-8"));
key = SecretKeyFactory.getInstance("DESede")
.generateSecret(keySpec);
iv = new IvParameterSpec(ivString.getBytes("UTF-8"));
} catch (Exception e) {
e.printStackTrace();
}
}
public String encrypt(String value) {
try {
Cipher ecipher = Cipher.getInstance("DESede/CFB8/NoPadding");
// "SunJCE");
ecipher.init(Cipher.ENCRYPT_MODE, key, iv);
if (value == null)
return null;
// Encode the string into bytes using utf-8
byte[] valeur = value.getBytes("UTF-8");
// Encrypt
byte[] enc = ecipher.doFinal(valeur);
// Encode bytes to base64 to get a string
String encodedString = new String(new Base32().encode(enc), "UTF-8");
StringBuilder sb = new StringBuilder();
for (int i = 0 ; i < encodedString.length(); ++i) {
if (0 != i && i % 4 == 0) {
sb.append("-");
}
sb.append(encodedString.charAt(i));
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
String encrypt = new CryptData("eSSuperKeyXXXXXXXXXXXXXX", "12345678").encrypt("770101K99N");
System.err.println(encrypt);
}
}
Приклад PHP-коду
<?php
class Base32
{
/**
* Table for encoding base32
*
* @var array
*/
private static $encode = array(
0 => 'A',
1 => 'B',
2 => 'C',
3 => 'D',
4 => 'E',
5 => 'F',
6 => 'G',
7 => 'H',
8 => 'I',
9 => 'J',
10 => 'K',
11 => 'L',
12 => 'M',
13 => 'N',
14 => 'O',
15 => 'P',
16 => 'Q',
17 => 'R',
18 => 'S',
19 => 'T',
20 => 'U',
21 => 'V',
22 => 'W',
23 => 'X',
24 => 'Y',
25 => 'Z',
26 => 2,
27 => 3,
28 => 4,
29 => 5,
30 => 6,
31 => 7,
32 => '=',
);
/**
* Table for decoding base32
*
* @var array
*/
private static $decode = array(
'A' => 0,
'B' => 1,
'C' => 2,
'D' => 3,
'E' => 4,
'F' => 5,
'G' => 6,
'H' => 7,
'I' => 8,
'J' => 9,
'K' => 10,
'L' => 11,
'M' => 12,
'N' => 13,
'O' => 14,
'P' => 15,
'Q' => 16,
'R' => 17,
'S' => 18,
'T' => 19,
'U' => 20,
'V' => 21,
'W' => 22,
'X' => 23,
'Y' => 24,
'Z' => 25,
2 => 26,
3 => 27,
4 => 28,
5 => 29,
6 => 30,
7 => 31,
'=' => 32,
);
/**
* Creates an array from a binary string into a given chunk size
*
* @param string $binaryString String to chunk
* @param integer $bits Number of bits per chunk
* @return array
*/
private static function chunk($binaryString, $bits)
{
$binaryString = chunk_split($binaryString, $bits, ' ');
if (substr($binaryString, (strlen($binaryString)) - 1) == ' ') {
$binaryString = substr($binaryString, 0, strlen($binaryString)-1);
}
return explode(' ', $binaryString);
}
/**
* Encodes into base32
*
* @param string $string Clear text string
* @return string Base32 encoded string
*/
public static function encode($string)
{
if (strlen($string) == 0) {
// Gives an empty string
return '';
}
// Convert string to binary
$binaryString = '';
foreach (str_split($string) as $s) {
// Return each character as an 8-bit binary string
$s = decbin(ord($s));
$binaryString .= str_pad($s, 8, 0, STR_PAD_LEFT);
}
// Break into 5-bit chunks, then break that into an array
$binaryArray = self::chunk($binaryString, 5);
// Pad array to be divisible by 8
while (count($binaryArray) % 8 !== 0) {
$binaryArray[] = null;
}
$base32String = '';
// Encode in base32
foreach ($binaryArray as $bin) {
$char = 32;
if (!is_null($bin)) {
// Pad the binary strings
$bin = str_pad($bin, 5, 0, STR_PAD_RIGHT);
$char = bindec($bin);
}
// Base32 character
$base32String .= self::$encode[$char];
}
return $base32String;
}
/**
* Decodes base32
*
* @param string $base32String Base32 encoded string
* @return string Clear text string
*/
public static function decode($base32String)
{
if (strlen($base32String) == 0) {
// Gives an empty string
return '';
}
// Only work in upper cases
$base32String = strtoupper($base32String);
// Remove anything that is not base32 alphabet
$pattern = '/[^A-Z2-7]/';
$base32String = preg_replace($pattern, '', $base32String);
$base32Array = str_split($base32String);
$string = '';
foreach ($base32Array as $str) {
$char = self::$decode[$str];
// Ignore the padding character
if ($char !== 32) {
$char = decbin($char);
$string .= str_pad($char, 5, 0, STR_PAD_LEFT);
}
}
while (strlen($string) %8 !== 0) {
$string = substr($string, 0, strlen($string)-1);
}
$binaryArray = self::chunk($string, 8);
$realString = '';
foreach ($binaryArray as $bin) {
// Pad each value to 8 bits
$bin = str_pad($bin, 8, 0, STR_PAD_RIGHT);
// Convert binary strings to ASCII
$realString .= chr(bindec($bin));
}
return $realString;
}
}
$base32 = new Base32;
$key = "eSSuperKey10050012345678";
$iv = "12345678";
$encoded = "ILDD-2V7W-SBWD-2X34";
echo "DECODED: " . mcrypt_decrypt(MCRYPT_3DES, $key, str_replace("-", "", $base32::decode($encoded)), MCRYPT_MODE_CFB, $iv) . "\n";
?>
Важливо!
Використовуйте Format Preserving Encryption, щоб спростити переведення коду в людиночитаний формат.