Перші кроки
Дані користувача
- Огляд адаптивного email-редактора
- Cтворення оформлення для листа
- Створення синхронізованих модулів
- Налаштування адаптивності
- Налаштування Smart-елементів
- Оформлення промовкладки для Gmail
- Додавання Ролловера
- Додавання анкорних посилань
- Бібліотека модулів
- Додавання таблиці до листа
- Додавання кастомних шрифтів
- Створення кнопки СТA
- Робота з блоком "Зображення"
- Використання ШІ в email-редакторі
Омніканальність
- SDK для мобільних застосунків
- Керування ключами доступу до мобільного SDK
- Підключення мобільного застосунку
- Створення та завантаження ключа Firebase
- Створення мобільних push-повідомлень
- Налаштування аналітики доставлень та кліків
- Планування мобільних push-повідомлень
- Налаштування універсальних посилань (deeplinks & Universal links)
- Надсилання тестових повідомлень із налагодження запитів
- Налаштування віджетів для сайту
- Виклик віджета
- Налаштування геоданих для правил виклику віджетів
- Збереження даних із віджетів у поля контактів
- Захист від роздратування
- Дії після заповнення форми
- Заміна системного сценарію Double Opt-In
- Розширення для тестування форм в Google Chrome
- Створення pop-up-форм за допомогою Google Tag Manager або WordPress
- Надсилання подій з віджетів eSputnik до Google Analytics
- A/B-тестування віджетів
Автоматизація
- Подвійне підтвердження підписки
- Вітальна серія
- Вітальна серія із сегментацією за категоріями
- Запуск сценарію після імпорту контактів
- Регулярний сценарій для групи
- Вітання з днем народження
- Привʼязка сценарію до кнопки
- Використання змінних із замовлення у сценарії
- Збір відгуків про замовлення
- Реактивація клієнтів та підписників
- Відправка розсилки непрочитавшим
- Налаштування додаткових розсилок
Персоналізація
- Підстановка промокоду з файлу
- Підстановка промокоду з використанням API
- Принципи генерації промокодів за допомогою PHP/JAVA
- Підстановка промокоду за допомогою персоналізації
- Завантаження промокодів для використання в сценарії
- Генерація промокодів у сценарії
- Відправлення промокоду за допомогою передпроцесора
- HTTP-запит для передачі промокоду з повідомлення до картки контакту
Аналітика
- Звіт щодо email-розсилки
- Звіт щодо SMS-розсилки
- Звіт щодо розсилки Web Push
- Звіт щодо Viber-розсилки
- Звіт щодо розсилки Mob Push
- Звіт щодо розсилки App Inbox
- Звіт зі взаємодії з віджетами
- Звіт щодо тригерної розсилки
- Звіт щодо AMP-розсилки
- Звіт щодо мультимовної розсилки
- Налаштування передачі UTM-міток
- Візуалізація доходу
- Відстеження ефективності розсилок у Google Analytics
Мультимовність
Відстеження подій та поведінки
- Відстеження активності на сайті за допомогою 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.
Передайте обидва ці значення в підтримку 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-коду
'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 = "eSSuperKeyXXXXXXXXXXXXXX"; $iv = "12345678"; $encoded = "ILDD-2V7W-SBWD-2X34"; echo "DECODED: " . mcrypt_decrypt(MCRYPT_3DES, $key, $base32::decode(str_replace("-", "", $encoded)), MCRYPT_MODE_CFB, $iv) . "\n"; ?>
Важливо!
Використовуйте Format Preserving Encryption, щоб спростити переведення коду в людиночитаний формат.