JavaScript SDK лендингов
window.SenlerLanding доступен в HTML-блоках опубликованного лендинга. SDK подключается автоматически до ваших скриптов; версия API — 1. Отдельный пакет устанавливать не нужно.
Выберите сегмент
Кнопке нужно указать, на какой сегмент подписывать посетителя. Для этого скопируйте ID нужного сегмента:
- Откройте настройки лендинга → «Разрешения».
- В разделе «Разрешения для HTML-блоков» добавьте нужный сегмент.
- Нажмите иконку копирования рядом с ID под названием сегмента.
- Вставьте скопированное значение в пример кода вместо
ID_СЕГМЕНТА.
Подробнее о выборе сегментов и разрешённых полей — в настройках HTML-форм.
Для обычной подписки достаточно segmentId. Остальные идентификаторы нужны только для отдельных сценариев:
| Параметр | Когда нужен |
|---|---|
segmentId | Обязателен для subscribe и unsubscribe: указывает сегмент подписки или отписки |
channelId | Необязателен для subscribe и unsubscribe: укажите его, если кнопка должна использовать конкретный канал проекта |
landingId | Нужен только для openLanding: указывает другой лендинг того же проекта, на который нужно перейти. В subscribe не передаётся |
Передайте внутренний ID сегмента в segmentId. Короткий ID из прямой ссылки подписки не подходит. Сегмент должен принадлежать проекту лендинга и быть доступен для публичной подписки. Разрешите сегмент в настройках HTML-форм и опубликуйте изменения. Подписка на сегмент агента также должна быть опубликована. Стандартная кнопка на странице не требуется.
Без channelId SDK использует подходящий канал текущего запуска или предлагает посетителю выбор. Явно заданный channelId имеет приоритет над каналом страницы. Если посетитель ещё не подтверждён в выбранном канале, откроется соответствующее приложение; данные пользователя из другого канала не используются для подписки.
Если нужно собрать контакты, contactCapture: { phone: true, email: true } включает запрос разрешённых контактов. Собственные поля передавайте через contact и variables: пример формы. Обязательные согласия сегмента сохраняются независимо от этих параметров.
Подписывается текущий посетитель с проверенным контекстом платформы. Передавать ID другого пользователя или самостоятельно подтверждать согласия через SDK нельзя. При копировании HTML в другой проект замените ID сегментов, каналов и лендингов.
Добавьте свою кнопку
Во вкладке HTML добавьте кнопку и место для результата:
<section>
<button type="button">Подписаться</button>
<p role="status" aria-live="polite"></p>
</section>
Во вкладке JS вставьте код без тегов <script> и замените ID_СЕГМЕНТА:
{
const root = document.currentScript.parentElement;
const button = root.querySelector('button');
const message = root.querySelector('[role="status"]');
const sdk = window.SenlerLanding;
const segmentId = 'ID_СЕГМЕНТА';
button.addEventListener('click', async () => {
button.disabled = true;
message.textContent = '';
try {
const result = await sdk.subscribe({ segmentId });
if (['subscribed', 'already_subscribed'].includes(result.status)) {
message.textContent = 'Вы подписаны!';
} else if (result.status === 'redirected') {
message.textContent = 'Продолжите подписку в приложении.';
} else if (result.status === 'cancelled') {
message.textContent = 'Подписка отменена.';
}
} catch (error) {
message.textContent = error.code === 'busy'
? 'Завершите текущую подписку.' : error.message;
} finally {
button.disabled = false;
}
});
}
Для оформления используйте CSS блока. SDK показывает штатные формы, согласия и запрос разрешения VK, когда они нужны.
Проверьте работу кнопки
Сохраните изменения и опубликуйте лендинг. Откройте публичную ссылку в браузере или нужной платформе и нажмите свою HTML-кнопку. Проверьте выбор канала, обязательные согласия и отображение результата в вашем коде. Подписка на опубликованной странице выполняется по-настоящему.
В предпросмотре редактора можно оценить HTML и CSS. JavaScript в нём не запускается.
Если лендинг открыт в обычном браузере
- Посетитель нажимает вашу кнопку подписки.
- SDK выбирает подходящий канал. Если нужен выбор, посетитель выбирает VK, Telegram или MAX из доступных каналов проекта.
- Открывается приложение выбранной платформы. Там Senler проверяет аккаунт посетителя и при необходимости показывает форму контактов и обязательные согласия. В VK для запроса разрешения на сообщения нужно действие посетителя внутри приложения: нажать «Подписаться» или подтвердить открытую форму.
- После успешного завершения SDK сообщает, что посетитель подписан. Теперь можно показать «Вы подписаны» или открыть следующий лендинг.
На исходной странице результат redirected означает «Открыли приложение». В этот момент подписка ещё не подтверждена. Для сообщения об успехе используйте только subscribed или already_subscribed. Если лендинг сразу открыт внутри нужной платформы, переход может не понадобиться.
Настройка каналов и приложений описана в руководстве по открытию лендингов. Если VK не разрешает запросить сообщения в приложении, используйте подсказки штатного окна подписки.
Если человек уже подписан
Повторный вызов subscribe для участника сегмента возвращает already_subscribed. Можно показать «Вы уже подписаны» или открыть те же материалы, что и после первой подписки.
Переданные разрешённые контакты и переменные обновляются и при повторной подписке. Нового события подписки при этом нет: автоматизация с запуском по новой подписке повторно не запустится. Например, повторная отправка формы может изменить город в карточке лида, но не запустит заново приветственную цепочку по этому событию. Правила сохранения полей описаны в статье про HTML-формы.
Покажите результат после подписки
Если человек перешёл в Telegram или VK, JavaScript исходной страницы может завершить работу. На открывшемся лендинге нужно отслеживать продолжение подписки. Для этого SDK позволяет прочитать текущее состояние и получать его изменения.
Оставьте HTML из примера кнопки, а содержимое вкладки JS замените кодом ниже. Он показывает «Спасибо» после подтверждения подписки, в том числе при продолжении внутри приложения. Замените ID_СЕГМЕНТА:
{
const root = document.currentScript.parentElement;
const button = root.querySelector('button');
const message = root.querySelector('[role="status"]');
const sdk = window.SenlerLanding;
const options = { segmentId: 'ID_СЕГМЕНТА' };
const nextLandingId = '';
let completedOperationId = null;
const messages = {
idle: 'Нажмите «Подписаться», чтобы продолжить.',
loading: 'Оформляем подписку…',
awaiting_input: 'Завершите выбор или заполнение формы.',
launching: 'Открываем приложение…',
redirected: 'Продолжите подписку в приложении.',
cancelled: 'Подписка отменена.',
unsubscribed: 'Вы отписаны.'
};
function showState(operations) {
const operation = operations.find((item) =>
item.segmentId === options.segmentId &&
item.channelId === (options.channelId ?? null)
);
if (!operation) return;
button.disabled = ['loading', 'awaiting_input', 'launching']
.includes(operation.status);
if (['subscribed', 'already_subscribed'].includes(operation.status)) {
message.textContent = 'Спасибо! Вы подписаны.';
if (nextLandingId && completedOperationId !== operation.operationId) {
completedOperationId = operation.operationId;
sdk.openLanding({ landingId: nextLandingId }).catch((error) => {
message.textContent = 'Вы подписаны. Не удалось открыть следующую страницу: ' + error.message;
});
}
} else {
message.textContent = messages[operation.status]
?? 'Подписка не завершена. Подробности показаны в окне подписки.';
}
}
sdk.onChange(showState);
showState(sdk.getOperations());
button.addEventListener('click', async () => {
if (button.disabled) return;
button.disabled = true;
completedOperationId = null;
message.textContent = 'Оформляем подписку…';
try {
await sdk.subscribe(options);
} catch (error) {
message.textContent = error.message;
} finally {
button.disabled = false;
}
});
}
Чтобы после подписки открыть другой лендинг, вставьте его внутренний ID в nextLandingId вместо пустой строки. Это должен быть другой включённый и опубликованный лендинг того же проекта. Переход сохраняет контекст платформы. Если нужна только надпись «Спасибо», оставьте строку пустой. Оба варианта работают и для уже подписанного посетителя.
В обычном браузере openLanding использует собственный адрес целевого лендинга, если он настроен. В MiniApp переход остаётся внутри соответствующей платформы; подставлять URL собственного домена вместо landingId не нужно.
onChange передаёт массив состояний и вызывается при изменениях. Он не вызывает обработчик сразу при подключении, поэтому пример отдельно читает начальное состояние через getOperations(). Код выбирает действие своего сегмента и канала. Если добавите channelId в options, тот же фильтр продолжит работать.
Эти методы показывают действия SDK на текущей странице, включая действие, переданное при открытии приложения. Они не возвращают список всех подписок посетителя. При обычном открытии ссылки список может быть пустым до нажатия кнопки. Слушатель удаляется автоматически при закрытии страницы.
Методы SDK
| Метод | Назначение |
|---|---|
subscribe({ segmentId, channelId?, contactCapture?, contact?, variables? }) | Начать подписку. phone и email в contactCapture — необязательные boolean |
unsubscribe({ segmentId, channelId? }) | Отписать текущего подтверждённого посетителя; без авторизованного запуска требуется сначала открыть страницу внутри платформы |
openLanding({ landingId }) | Открыть опубликованный лендинг того же проекта по внутреннему ID, сохранив контекст платформы |
openUrl({ url }) | Открыть абсолютный HTTP(S) URL. Вызывайте непосредственно из обработчика клика |
getOperations() | Получить состояния операций SDK: operationId, segmentId, channelId, status |
onChange(callback) | Получать обновления состояний. Возвращает функцию отписки от обновлений |
onDispose(callback) | Зарегистрировать очистку при уходе со страницы. Возвращает функцию снятия обработчика |
В contact передавайте только phone и email: непустые строки длиной до 120 и 320 символов соответственно. Email должен быть корректным адресом. Необязательное пустое поле не отправляйте; передать пустую строку для очистки контакта нельзя.
Ключи variables — точные имена разрешённых переменных лида, например { city: "Москва", age: 25 }, а не lead.city или ID определения. Значения должны соответствовать типам переменных. Ограничения и порядок включения полей описаны в настройке HTML-формы. contactCapture открывает штатные поля ввода, а contact передаёт уже собранные значения; оба варианта требуют разрешения этих контактов в настройках лендинга.
Примеры других действий:
await SenlerLanding.unsubscribe({ segmentId: 'ID_СЕГМЕНТА' });
await SenlerLanding.openLanding({ landingId: 'ID_ЛЕНДИНГА' });
await SenlerLanding.openUrl({ url: 'https://example.com' });
Результат и ошибки
subscribe и unsubscribe возвращают Promise с { operationId, status } после завершения текущего сценария. Пока посетитель выбирает канал, заполняет форму или подтверждает разрешение, Promise остаётся в ожидании. Обычной кнопке достаточно await и try/catch; подписка на глобальные события не нужна.
В результате status равен subscribed, already_subscribed, unsubscribed, cancelled или redirected. Отмена — обычный результат, а не ошибка. Технические ошибки и невозможность подписки отклоняют Promise. После перехода в другое приложение исходная страница может закрыться: её Promise не переносится на новую страницу, выполнение кода после await не гарантируется. Подтверждённая подписка и передача управления в приложение — разные результаты.
onChange и getOperations() нужны для расширенного отображения промежуточных состояний и продолженного запуска. Для одного сегмента и канала сохраняется последняя операция на текущей странице.
loading и launching означают обработку, awaiting_input — форму или выбор канала. subscribed и already_subscribed подтверждают подписку, unsubscribed — отписку. cancelled означает закрытие формы, выбора канала или отказ от разрешения VK. redirected означает только переход: исходная страница не объявляет подписку успешной без подтверждения. После перехода в приложение SDK продолжит сценарий с тем же сегментом и настройками.
unavailable, verification_required, consent_required и error описывают невозможность завершить операцию. Штатный интерфейс показывает подробности ошибки. Одновременно выполняется один сценарий подписки.
Ошибки ловите через try/catch: invalid_argument — неверные параметры, busy — уже выполняется сценарий, unavailable — нет доступного канала, not_ready — страница закрыта, timeout — запрос подготовки подписки или адреса лендинга не завершился за 15 секунд. Такие запросы отменяются при закрытии страницы; после таймаута подготовку можно повторить. Уже отправленная подписка автоматически не повторяется. request_failed означает сбой запроса или выполнения; consent_required — отсутствие необходимых согласий, verification_required — неподтверждённого посетителя. Ошибка содержит code, message и, если сценарий уже начался, operationId. При закрытии страницы незавершённый Promise отклоняется с not_ready: это не отменяет уже отправленный запрос подписки и не доказывает его неуспех. Удаление сегмента, отключение лендинга или смена публикации может сделать ранее полученный контекст недоступным.
Статистика подписки относится к лендингу и наблюдаемому содержимому. У произвольной HTML-кнопки нет строки стандартного блока кнопки в статистике кликов.
Если кнопка не работает
| Что происходит | Что проверить |
|---|---|
| В редакторе кнопка не реагирует | Откройте опубликованную ссылку: предпросмотр не выполняет JavaScript |
| После правки ничего не изменилось | Дождитесь сохранения, опубликуйте изменения и заново откройте публичную ссылку. Лендинг агента публикуется вместе с агентом |
SDK сообщает о неверных параметрах (invalid_argument) | Скопируйте внутренний ID сегмента из настроек разрешений. Проверьте, что заменили ID_СЕГМЕНТА, а в subscribe не передали адрес страницы, landingId или короткий публичный ID |
| Подписка или запись полей запрещена | Разрешите выбранный сегмент, контакты и переменные в настройках HTML-форм, затем опубликуйте лендинг. Для сегмента агента проверьте публикацию подписки агента |
Нет доступного канала (unavailable) | Проверьте, что нужный канал включён и настроен для лендингов. Если в коде задан channelId, проверяйте именно этот канал |
| Приложение открылось, но подтверждения подписки нет | Завершите действия внутри приложения: форму, согласия и разрешение на сообщения. Для VK может потребоваться повторно нажать «Подписаться» уже там. Сам переход не подтверждает подписку |
SDK сообщает, что действие уже выполняется (busy) | Завершите или отмените открытую форму либо выбор канала. Одновременно выполняется один сценарий подписки |
| Человек уже подписан, но автоматизация не запускается снова | Повторная подписка не создаёт новое событие. Проверьте поведение для участника сегмента |
Если причина остаётся непонятной, сохраните текст ошибки, её code и operationId, если он есть, вместе с публичной ссылкой на лендинг. Эти данные помогут поддержке найти неудачную попытку.
Выполнение и очистка скриптов
Скрипты работают в вебе, VK App, Telegram Mini App и MAX Mini App. В предпросмотре редактора JS не выполняется. Поддерживаются обычные <script>, модули и внешние HTTP(S)-файлы. Код вкладки JS выполняется после скриптов в HTML того же блока; теги запускаются по порядку блоков; загрузка внешнего скрипта или модуля ограничена 15 секундами. Повторная отрисовка состояния не перезапускает код. Вместо удаляемых атрибутов onclick используйте addEventListener.
Код имеет доступ к DOM и данным публичной страницы, как Tag Manager. Используйте доверенные скрипты. Убирайте свои таймеры и глобальные обработчики при закрытии:
const timer = setInterval(() => {}, 1000);
SenlerLanding.onDispose(() => clearInterval(timer));
Слушатели onChange удаляются автоматически. Сохранённый SDK закрытой страницы больше не запускает операции.