# Динамический контент в варианте персонализации
Внутри каждого варианта персонализации можно добавлять как статический, так и динамический контент. Если нужно реагировать на данные посетителя — город, устройство, UTM-метки, погоду, время суток — используйте JavaScript-код прямо в шаблоне.
Это позволяет, например:
- Показывать название города посетителя в заголовке
- Менять призыв к действию в зависимости от устройства
- Подставлять количество клиентов в регионе
- Предлагать разные акции в рабочие и выходные дни
- Адаптировать текст под погодные условия
# Как это работает
Внутри поля "Контент" можно вставить JavaScript-код в двойных фигурных скобках (например, {{ return "Привет"; }}). Система обработает код на сервере и подставит результат перед отправкой контента в браузер посетителя.
Доступны все стандартные функции JavaScript: Math, String, Array, условные операторы, циклы и т.д.
Важно:
- Если код выполнится с ошибкой — посетитель увидит контент без изменений, страница не сломается
- Код выполняется в изолированной среде — нет доступа к DOM, window, fetch или другим браузерным API
- Каждый JS-блок в двойных фигурных скобках выполняется независимо
# Базовые примеры
# Простое выражение
Сумма 2 + 2 = {{2+2}}
Результат: Сумма 2 + 2 = 4
Для простых выражений без условий можно опустить return. Но если код содержит несколько строк или условия — используйте return явно.
# Условный оператор
10 больше двух? - {{
if (10 > 2) {
return "Да";
} else {
return "Нет";
}
}}
Результат: 10 больше двух? - Да
# Тернарный оператор
Для коротких условий удобен тернарный оператор:
Скидка: {{data.session.number > 1 ? "10% для постоянных клиентов" : "5% на первый заказ"}}
# Вложенные функции
Сумма 99 и 1 равна {{
function sum(arg1, arg2) {
return arg1 + arg2;
}
return sum(99, 1);
}}
Результат: Сумма 99 и 1 равна 100
Если используете вложенные функции — не забывайте явно возвращать результат через
return.
# Несколько скриптов в одном контенте
В одном поле контента может быть сколько угодно JS-блоков в двойных фигурных скобках:
{{5 + 5}} больше {{4 - 2}}? - {{return "Да";}}
Результат: 10 больше 2? - Да
Будьте аккуратны: большое количество скриптов может замедлить вычисление контента.
# Контекст: переменная data
Внутри JS-кода доступна переменная data — объект с информацией о текущем посетителе. Данные собираются автоматически при каждом визите: по IP определяется город, по User-Agent — устройство, по URL — UTM-метки, со страницы — Schema.org разметка.
Все поля data доступны только для чтения.
# Практические примеры
# Город и регион посетителя
Самый популярный сценарий — подстановка города в текст:
Доставка в г. {{data.geo.city.nativeName}} за 1 день
Результат для москвича: Доставка в г. Москва за 1 день
Для регионального контента:
{{
let city = data.geo.city.nativeName;
if (!city) {
return "Доставка по всей России";
}
return "Доставка в " + city + " и " + data.geo.region.nativeName;
}}
Всегда проверяйте
data.geo.city.nativeNameнаnull— город определяется по IP и может быть неизвестен (например, при использовании VPN).
# Столица или нет
{{
if (data.geo.city.isCountryCapital) {
return "Бесплатная доставка по Москве";
} else if (data.geo.city.isRegionCapital) {
return "Бесплатная доставка по областному центру";
} else {
return "Доставка от 300 ₽";
}
}}
# Размер города
{{
let pop = data.geo.city.population;
if (!pop) return "Доставка по вашему городу";
if (pop > 1000000) {
return "Доставка по городу-миллионнику — от 0 ₽";
} else if (pop > 100000) {
return "Доставка по вашему городу — от 200 ₽";
} else {
return "Доставка до пункта выдачи — от 350 ₽";
}
}}
# Приветствие по времени суток
{{
if (data.dateAndTime.isMorning) {
return "Доброе утро! ☀️";
} else if (data.dateAndTime.isNight) {
return "Не спится? У нас скидка на ночные заказы 🌙";
} else if (data.dateAndTime.isWeekend) {
return "Отличных выходных! 🎉";
} else {
return "Добрый день!";
}
}}
# Контент по часу
{{
let hour = data.dateAndTime.clientLocalHour;
if (hour >= 9 && hour < 18) {
return "Менеджер онлайн — ответим за 5 минут";
} else {
return "Оставьте заявку — ответим утром";
}
}}
# Выходные и рабочие дни
{{
if (data.dateAndTime.isWeekend) {
return "В выходные скидка 15% на весь каталог!";
} else {
return "Скидка 10% при заказе до конца рабочей недели";
}
}}
# Адаптация под устройство
{{
if (data.device.deviceType === "Smartphone") {
return "Скачайте наше приложение — скидка 20%";
} else if (data.device.deviceType === "Tablet") {
return "Удобный каталог для планшета";
} else {
return "Полный каталог на десктопе";
}
}}
# Контент по браузеру
{{
if (data.device.browser === "Safari" || data.device.os === "iOS") {
return "Оплата через Apple Pay";
} else {
return "Оплата картой или через SberPay";
}
}}
# Контент по UTM-меткам
{{
let source = data.utm.source;
if (source === "google") {
return "Нашли нас в Google? Вот промокод: GOOGLE10";
} else if (source === "yandex") {
return "Пришли из Яндекса? Промокод: YANDEX10";
} else {
return "Промокод для новых клиентов: WELCOME10";
}
}}
# По рекламной кампании
{{
let campaign = data.utm.campaign;
if (campaign && campaign.indexOf("black_friday") !== -1) {
return "🖤 Чёрная пятница — скидки до 70%!";
} else if (campaign && campaign.indexOf("summer") !== -1) {
return "☀️ Летняя распродажа!";
} else {
return "Специальное предложение";
}
}}
# Погода
{{
let temp = data.weather.temp;
if (temp === null) return "Бесплатная доставка";
if (temp < 0) {
return "На улице " + temp + "°C — закажите горячий чай с доставкой ☕";
} else if (temp > 30) {
return "Жара " + temp + "°C! Прохладительные напитки со скидкой 🧊";
} else {
return "Доставка при любой погоде";
}
}}
Погодные данные определяются по городу посетителя. Если город не определён —
data.weather.tempбудетnull.
# Повторные визиты
{{
let sessionNum = data.session.number;
if (sessionNum === 1) {
return "Добро пожаловать! Скидка 5% на первый заказ";
} else if (sessionNum <= 3) {
return "Рады видеть вас снова! Бесплатная доставка на второй заказ";
} else {
return "Для постоянных клиентов — персональная скидка 15%";
}
}}
# Время на сайте
{{
let duration = data.session.durationSec;
if (duration > 300) {
return "Долго выбираете? Давайте поможем — напишите в чат!";
} else {
return "";
}
}}
# Количество просмотренных страниц
{{
let pages = data.session.pagesOpenedInThisSession;
if (pages >= 5) {
return "Вы посмотрели уже " + pages + " страниц. Может, пора заказать? 😉";
} else {
return "";
}
}}
# Цена товара со страницы (Schema.org)
Если на странице есть Schema.org-разметка (HTML Microdata или JSON-LD), данные автоматически извлекаются:
{{
let price = data.page.schemaOrg.offer.price;
if (price && price > 5000) {
return "При заказе от 5 000 ₽ — бесплатная доставка!";
} else {
return "Доставка от 300 ₽";
}
}}
# Рейтинг товара
{{
let rating = data.page.schemaOrg.aggregateRating.ratingValue;
let reviews = data.page.schemaOrg.aggregateRating.reviewCount;
if (rating && rating >= 4.5 && reviews > 10) {
return "⭐ Хит продаж! Рейтинг " + rating + " (" + reviews + " отзывов)";
} else {
return "";
}
}}
# Комбинация нескольких параметров
{{
let city = data.geo.city.nativeName || "вашем городе";
let device = data.device.deviceType;
let isWeekend = data.dateAndTime.isWeekend;
let text = "Доставка в " + city;
if (isWeekend) {
text += " работает и в выходные!";
}
if (device === "Smartphone") {
text += " Закажите через приложение — скидка 5%.";
}
return text;
}}
# Шаблонные функции
# simulateCityClients(min, max)
Возвращает правдоподобное количество клиентов в городе посетителя. Учитывает население города, размер агломерации и экономический индекс. Результат всегда находится в диапазоне от min до max.
Количество выполненных заявок в вашем городе — {{ simulateCityClients(500, 2000) }}
Результат для Москвы: Количество выполненных заявок в вашем городе — 1847
Результат для небольшого города: Количество выполненных заявок в вашем городе — 612
Если город не определён, возвращается среднее значение (min + max) / 2.
Пример с контекстом:
Уже {{simulateCityClients(100, 800)}} клиентов в г. {{data.geo.city.nativeName || "вашем регионе"}} выбрали нас
# log(message)
Записывает сообщение в лог для отладки. Не влияет на результат и не виден посетителю.
{{
log("City: " + data.geo.city.nativeName);
log("Session: " + data.session.number);
return "Привет!";
}}
# Полный справочник параметров data
# Геолокация: город
| Параметр | Описание | Тип | Пример |
|---|---|---|---|
data.geo.city.nativeName | Название на родном языке | string | "Москва", "Paris" |
data.geo.city.englishName | Название на английском | string | "Moscow" |
data.geo.city.russianName | Название на русском | string | "Москва", "Париж" |
data.geo.city.isRegionCapital | Столица региона | bool | true |
data.geo.city.isCountryCapital | Столица страны | bool | true |
data.geo.city.population | Население | number | 12500000 |
data.geo.city.agglomerationPopulation | Население агломерации | number | 17100000 |
data.geo.city.averageSalaryUSD | Средняя зарплата (USD) | number | 99.9 |
data.geo.city.economicLocalIndex | Экономический индекс (0–100) | number | 75.3 |
# Геолокация: регион
| Параметр | Описание | Тип | Пример |
|---|---|---|---|
data.geo.region.nativeName | Название на родном языке | string | "Московская область" |
data.geo.region.englishName | Название на английском | string | "Moscow Oblast" |
data.geo.region.russianName | Название на русском | string | "Московская область" |
data.geo.region.population | Население региона | number | 7500000 |
# Геолокация: страна
| Параметр | Описание | Тип | Пример |
|---|---|---|---|
data.geo.country.nativeName | Название на родном языке | string | "Россия" |
data.geo.country.englishName | Название на английском | string | "Russia" |
data.geo.country.russianName | Название на русском | string | "Россия" |
data.geo.country.population | Население страны | number | 146000000 |
# Данные страницы
| Параметр | Описание | Тип | Пример |
|---|---|---|---|
data.page.pageClearedUrl | URL страницы (без трекинг-параметров) | string | "/catalog/phones" |
data.page.pageTitle | Заголовок страницы | string | "Каталог телефонов" |
# Данные страницы: Schema.org
Автоматически извлекаются из HTML Microdata и JSON-LD разметки на странице.
| Параметр | Описание | Тип | Пример |
|---|---|---|---|
data.page.schemaOrg.brandName | Бренд | string | "Apple" |
data.page.schemaOrg.offer.price | Цена | number | 99990 |
data.page.schemaOrg.offer.availability | Наличие | string | "InStock" |
data.page.schemaOrg.aggregateRating.ratingValue | Средний рейтинг | number | 4.5 |
data.page.schemaOrg.aggregateRating.reviewCount | Количество отзывов | number | 120 |
# Погода
Определяется по городу посетителя. Если город не определён — все значения null.
| Параметр | Описание | Тип | Пример |
|---|---|---|---|
data.weather.temp | Температура (°C) | number | 22.5 |
data.weather.tempFeelsLike | Ощущаемая температура (°C) | number | 20.0 |
data.weather.humidity | Влажность (%) | number | 65 |
# Устройство
| Параметр | Описание | Тип | Возможные значения |
|---|---|---|---|
data.device.browser | Браузер | string | "Chrome", "Safari", "Edge", "Opera", "Firefox", "YandexBrowser", "InternetExplorer", "Other" |
data.device.deviceType | Тип устройства | string | "Desktop", "Smartphone", "Tablet", "Other" |
data.device.os | Операционная система | string | "Windows", "MacOs", "Linux", "iOS", "Android", "Other" |
# UTM-метки
| Параметр | Описание | Тип | Пример |
|---|---|---|---|
data.utm.source | Источник | string | "google" |
data.utm.medium | Канал | string | "cpc" |
data.utm.campaign | Кампания | string | "summer_sale" |
data.utm.content | Контент | string | "banner_1" |
data.utm.term | Ключевое слово | string | "best_deals" |
# Дата и время
Время определяется по часовому поясу посетителя.
| Параметр | Описание | Тип | Пример |
|---|---|---|---|
data.dateAndTime.clientLocalHour | Локальный час (0–23) | number | 14 |
data.dateAndTime.dayOfWeekNumber | День недели (1–7) | number | 3 |
data.dateAndTime.weekNumberInMonth | Неделя в месяце (1–5) | number | 2 |
data.dateAndTime.isNight | Ночь (22:00–06:00) | bool | false |
data.dateAndTime.isMorning | Утро (06:00–11:00) | bool | true |
data.dateAndTime.isWeekend | Выходной | bool | false |
# Сессия
| Параметр | Описание | Тип | Пример |
|---|---|---|---|
data.session.number | Номер визита пользователя (начиная с 1) | number | 3 |
data.session.durationSec | Длительность текущей сессии (секунды) | number | 245.5 |
data.session.pagesOpenedInThisSession | Страниц открыто в текущей сессии | number | 5 |
# Обработка ошибок и null-значений
Любое поле data может быть null — например, если город не определён по IP или на странице нет Schema.org-разметки. Всегда проверяйте значения перед использованием:
// ❌ Плохо — упадёт если город не определён
Доставка в {{data.geo.city.nativeName}}
// ✅ Хорошо — с проверкой
Доставка в {{data.geo.city.nativeName || "ваш город"}}
// ✅ Хорошо — развёрнутая проверка
{{
let city = data.geo.city.nativeName;
if (city) {
return "Доставка в " + city;
}
return "Доставка по России";
}}
Если код внутри JS-блока выбросит ошибку, посетитель увидит контент без этой подстановки — страница не сломается.
# Советы
- Начинайте с простого. Подставьте город в заголовок — это уже даст персонализированный контент
- Проверяйте null. Самая частая ошибка — обращение к полю, которое не определено
- Тестируйте в отладке. Используйте отладочный режим, чтобы увидеть результат шаблонов на реальной странице
- Используйте
log(). Для отладки сложных шаблонов записывайте промежуточные значения - Комбинируйте условия. Самые эффективные шаблоны учитывают несколько параметров — город + устройство + время
# Следующие шаги
← Варианты Управление →