Что такое пиксель и как он работает
Пиксель Telegram Ads — это небольшой JS-скрипт, который вы размещаете на своем сайте. Он передает в рекламный кабинет информацию о действиях пользователя после перехода по объявлению. Например:
- просмотр страницы,
- отправка формы,
- оформление заказа и др.
Важно: пиксель не хранит персональные данные. Всё собирается в агрегированном виде.
Telegram Ads использует модель атрибуции Post-View. Это значит, что, даже если пользователь просто увидел рекламу (но не кликнул), а позже сам нашел сайт и совершил действие, оно всё равно засчитается.
Что это значит для разработчика:
- Telegram хранит информацию о просмотре на стороне сервера (возможно, по IP + fingerprint + тайм-метка).
- Пиксель не использует cookies или localStorage на клиенте.
- Это усложняет отладку: события могут быть приняты и обработаны, но не отображены в статистике сразу (если нет связи с показом/кликом).

Общая схема настройки пикселя
Чтобы пиксель начал работать, нужно сделать три вещи:
- Установить базовый код (Base Code) на сайт.
- Создать событие (например, «Заявка») и получить Event Code.
- Привязать событие к объявлению при его создании.
Установка базового пикселя на сайт
Base Code — это основной фрагмент кода, который должен быть размещен на всех страницах сайта. Он не отслеживает действия, а лишь подготавливает сайт к их фиксации.
Вот где его взять:
1. Перейдите в кабинет Telegram Ads → раздел Manage Events.

2. Нажмите Create a pixel.

3. Скопируйте код Base Code, который появится во всплывающем окне.

4. Далее добавьте этот код в раздел <HEAD> вашего сайта. Разберем это на популярных примерах.
Примечание для разработчика:
- Скрипт загружается синхронно.
- Инициализирует глобальную функцию
window.tgp(...)
. - Отложенные вызовы (
tgp.queue
) сохраняются до полной загрузки скрипта.
Основной скрипт должен быть размещен на всех страницах сайта, иначе события не будут отправляться (в SPA обрабатывается отдельно, см. ниже).
Совсем простой вариант для сайта на Tilda
- Зайдите на tilda.ru/projects, выберите нужный сайт → «Настройки сайта».
- Перейдите в раздел «Ещё» → «HTML-код для вставки в <HEAD>».
- Вставьте код из Telegram в открывшееся поле.
- Сохраните изменения и опубликуйте все страницы сайта.
Вариант для продвинутых через Google Tag Manager или напрямую в код
Если вы используете GTM, то вставьте Base Code как пользовательский HTML-тег, который срабатывает на всех страницах.
Создаем событие для отслеживания действий (Event Code)
После установки базового кода самое время создать событие, которое будет фиксировать нужное нам действие — например, отправку формы или нажатие кнопки «Оформить заказ».
Шаги:
1. В Telegram Ads перейдите в Manage Events.

2. Нажмите Add an Event.
3. В появившемся окне задайте:
- название события (например, Заявка);
- тип события (например, Lead / Sign Up — это влияет только на название, не на работу пикселя);
- нажмите Save.

Как передаются события
Telegram не раскрывает подробности работы пикселя, но по опыту такие технологии используют один из стандартных протоколов отправки данных, вероятнее всего navigator.sendBeacon или fetch. Отправка событий происходит в фоне, без блокировки основного потока.
Формат запроса, судя по заголовкам в devtools, — минимальный JSON с идентификатором пикселя, ID события и, возможно, информацией о браузере и сессии.
Настраиваем отслеживание события на сайте
После создания события Telegram покажет два кода:
- Base Code (мы уже установили).
- Event Code — именно он нужен для фиксации конкретного действия на сайте.
Из Event Code нам нужен ID события — это набор символов, который следует сразу после tgp('event', '...')
.

Как «прикрепить» событие к кнопке отправки формы (на примере Tilda):
1. Перейдите на свой сайт и найдите кнопку, нажатие которой вы хотите отслеживать.
2. Кликните по кнопке правой кнопкой → Просмотреть код (в браузере).
3. Найдите значение внутри class="..."
и запомните текст кнопки (например: t-submit, текст: Отправить).

4. Перейдите в «Настройки сайта» → «Ещё» → «HTML-код для HEAD».
5. Вставьте следующий шаблон кода под уже добавленным Base Code:
<script>
window.addEventListener('load', function () {
const eventCode = 'EVENT_ID';
const buttonSelector = '.КЛАСС_КНОПКИ';
const expectedText = 'ТЕКСТ_КНОПКИ';
const submitButton = document.querySelector(buttonSelector);
if (submitButton) {
submitButton.addEventListener('click', function () {
const buttonText = submitButton.textContent.trim();
if (buttonText.includes(expectedText)) {
tgp('event', eventCode);
console.log('Событие отправлено');
} else {
console.log(`Текст кнопки не соответствует: "${buttonText}"`);
}
});
} else {
console.log('Кнопка не найдена');
}
});
</script>
6. Замените:
'EVENT_ID'
на ID вашего события;'.КЛАСС_КНОПКИ'
на класс кнопки (с точкой вначале);'ТЕКСТ_КНОПКИ'
на текст, отображаемый на кнопке.
7. Нажмите «Сохранить». Вернитесь в «Мои сайты» и нажмите «Опубликовать все страницы».
Проверяем, работает ли событие
Перед запуском рекламы убедимся, что событие действительно срабатывает.
Способ через консоль браузера:
- Откройте сайт.
- Кликните правой кнопкой мыши → «Просмотреть код» → вкладка «Консоль».
- Заполните форму и нажмите кнопку.
Если всё сделано правильно, в консоли появится сообщение: 'событие отправлено'
.
Кроме того, можно проверить в Telegram Ads:
- Перейдите в раздел Manage Events.
- В колонке Last Event Time появится время последнего срабатывания.

Для продвинутых вот еще список более точных методов проверки:
Проверка через вкладку Network
- Откройте DevTools (F12) на нужной странице.
- Перейдите на вкладку Network.
- Фильтруйте по ключевым словам:
tgp
,event
,beacon
,collect
,telegrampixel
,pixel
,event
. - Выполните целевое действие (например, нажмите на кнопку).
- Ищите в списке XHR или Beacon-запрос, отправленный на сервер Telegram.
Как выглядит:
- Тип запроса:
beacon
илиfetch
. - Адрес: может быть вида
https://ads-telegram-collect.telegram.org/…
- Статус: 200 OK или 204 No Content.
- Тело запроса (payload) будет содержать ID события, ID пикселя и метаданные.
Если вы не видите таких запросов, скорее всего, скрипт не загрузился или событие не вызвалось.
Локальный мок-режим (эмуляция без отправки)
Если вы не хотите реально слать события в Telegram (например, на этапе разработки), можно захардкодить мок-функцию, которая имитирует отправку, но ничего не делает.
Пример:
if (typeof window.tgp !== 'function') {
window.tgp = function (...args) {
console.log('MOCK: tgp called with:', args);
};
}
Полезно, если вы работаете локально без подключения скрипта Telegram или в staging-среде.
Безопасная обертка для SPA
Создайте функцию, которая будет надежно и безопасно вызывать событие:
export function sendTelegramEvent(eventId: string) {
if (typeof window !== 'undefined' && typeof window.tgp === 'function') {
window.tgp('event', eventId);
console.log(`[Telegram Pixel] Sent event: ${eventId}`);
} else {
console.warn(`[Telegram Pixel] Not ready. Event "${eventId}" not sent`);
}
}
Так вы сможете контролировать, вызвано событие или нет.
React: useEffect + useRef
А вот пример для технологии React: отправка события при нажатии кнопки.
import { useEffect, useRef } from 'react';
import { sendTelegramEvent } from './telegramPixel';
export const SubmitButton = () => {
const buttonRef = useRef<HTMLButtonElement | null>(null);
useEffect(() => {
const btn = buttonRef.current;
if (!btn) return;
const handleClick = () => sendTelegramEvent('EVENT_ID');
btn.addEventListener('click', handleClick);
return () => {
btn.removeEventListener('click', handleClick);
};
}, []);
return (
<button ref={buttonRef} className="submit-btn">
Отправить заявку
</button>
);
};
Так выглядит отправка события при монтировании страницы.
useEffect(() => {
sendTelegramEvent('LANDING_VIEW_EVENT');
}, []);
Кроме того, нужно для контроля вызова событий.
Vue 3: lifecycle hook + ref
Аналогичный пример только уже для Vue 3.
<template>
<button ref="submitButton">Отправить</button>
</template>
<script setup>
import { onMounted, ref, onBeforeUnmount } from 'vue';
import { sendTelegramEvent } from './telegramPixel';
const submitButton = ref(null);
const handleClick = () => sendTelegramEvent('EVENT_ID');
onMounted(() => {
submitButton.value?.addEventListener('click', handleClick);
});
onBeforeUnmount(() => {
submitButton.value?.removeEventListener('click', handleClick);
});
</script>
Поддержка роутинга (React Router, Vue Router)
SPA-приложения часто не перезагружают страницу при смене маршрута. Это значит, что событие PageView не произойдет само — его нужно вызывать вручную.
Пример для React Router (v6):
import { useLocation } from 'react-router-dom';
import { useEffect } from 'react';
import { sendTelegramEvent } from './telegramPixel';
const useTelegramPageView = () => {
const location = useLocation();
useEffect(() => {
sendTelegramEvent('PAGE_VIEW_EVENT_ID');
}, [location.pathname]);
};
Используйте useTelegramPageView()
в компоненте верхнего уровня (App
, Layout
, RoutesWrapper
и т. д.), чтобы это событие срабатывало самым первым на странице.
Распространенные проблемы на проде
Выше я рассмотрел совсем типичный пример проверки работоспособности событий, и хотя интеграция пикселя Telegram Ads может показаться тривиальной, в реальных боевых условиях часто возникают ситуации, при которых события не отправляются, хотя код формально «вроде как есть».
Вот самые распространенные проблемы, с которыми сталкиваются разработчики.
Событие отправляется до загрузки пикселя
tgp('event', 'EVENT_ID')
; // вызывает ошибку или молча не отрабатывает.
Почему это происходит:
- Base Code (глобальный
tgp
) еще не успел инициализироваться. - Вызывается
tgp()
до того, как<script>
с пикселем подключен. - В Single Page Application (SPA) или при динамической подгрузке компонентов
tgp
может быть вообще не определен на момент вызова.
Как решить:
- Проверять наличие
window.tgp
перед вызовом:
if (typeof window.tgp === 'function') {
tgp('event', 'EVENT_ID');
} else {
console.warn('tgp is not ready yet');
}
- Использовать retry-логику с таймером или обработчик загрузки скрипта:
function sendEventWhenReady(eventId) {
const interval = setInterval(() => {
if (typeof window.tgp === 'function') {
tgp('event', eventId);
clearInterval(interval);
}
}, 300);
}
sendEventWhenReady('EVENT_ID');
Кнопка появляется динамически (AJAX, SPA)
Сценарий:
- Кнопка создается через JS после загрузки страницы.
- Вы привязали обработчик
click
к элементу, которого еще нет в DOM. - В результате
document.querySelector(...)
не находит элемент, и обработчик не вешается.
Как решить:
- Использовать
MutationObserver
:
const observer = new MutationObserver(() => {
const btn = document.querySelector('.t-submit');
if (btn) {
btn.addEventListener('click', () => {
tgp('event', 'EVENT_ID');
});
observer.disconnect(); // больше не следим
}
});
observer.observe(document.body, { childList: true, subtree: true });
- Или использовать
setInterval
/setTimeout
как fallback:
const interval = setInterval(() => {
const btn = document.querySelector('.t-submit');
if (btn) {
btn.addEventListener('click', () => tgp('event', 'EVENT_ID'));
clearInterval(interval);
}
}, 300);
DOM не готов, событие вешается слишком рано
Проблема:
- Вы вешаете
addEventListener
на кнопку в<head>
или сразу после открытия тега<body>
. - DOM еще не построен —
document.querySelector()
возвращаетnull
.
Как решить:
- Оборачивать код в
window.addEventListener('load', ...)
:
window.addEventListener('load', function () {
const btn = document.querySelector('.t-submit');
if (btn) {
btn.addEventListener('click', () => tgp('event', 'EVENT_ID'));
}
});
- Альтернатива: использовать
DOMContentLoaded
, если пиксель подключается до остальных JS:
document.addEventListener('DOMContentLoaded', function () {
// ...
});
Событие не триггерится из-за JS-фреймворка
Типичные причины:
- В React, Vue, Angular или Svelte вы не работаете напрямую с DOM.
- Кнопка — компонент, и его перерисовка «съедает» повешенный вручную обработчик.
- После перехода по роуту в SPA DOM обновился, а JS-пиксель не знал об этом.
Как решить:
- Использовать системный хук/эффект.
Пример для React:
useEffect(() => {
const btn = document.querySelector('.submit-btn');
if (btn) {
const handler = () => tgp('event', 'EVENT_ID');
btn.addEventListener('click', handler);
return () => btn.removeEventListener('click', handler);
}
}, []);
Пример для Vue:
mounted() {
const btn = this.$el.querySelector('.submit-btn');
btn?.addEventListener('click', () => tgp('event', 'EVENT_ID'));
}
Важно: если вы используете роутинг внутри SPA (например, react-router
, vue-router
), проверяйте, не сбрасываются ли слушатели после навигации. Инициализируйте их после каждой смены маршрута.
Привязываем событие к объявлению в Telegram Ads
Хорошо, разобрались со всеми серьезными правилами постановки пикселя, теперь надо привязать событие к объявлению, иначе ничего работать не будет. Для этого осталось указать, какое именно событие считать конверсией при запуске рекламы.
Шаги:
1. В рекламном кабинете Telegram Ads нажмите Create a new ad.
2. Заполните:
- URL you want to promote — ссылку на сайт (не забудьте про UTM-метки);
- Website name — заголовок для отображения в рекламе.

3. Прокрутите страницу почти до конца и найдите поле Conversion event.

4. В выпадающем списке выберите нужное событие (например, «Заявка»), которое вы создали ранее.
Важно: можно выбрать только одно событие на одно объявление.
После запуска рекламы Telegram Ads начнет автоматически фиксировать все выполненные действия по заданному событию прямо в статистике объявления.
Что дальше: данные, оптимизация и тесты
Поздравляю! Вы настроили пиксель Telegram Ads, и теперь:
- данные о заявках, покупках и других действиях пользователей отображаются прямо в кабинете Telegram, без необходимости использовать сторонние аналитические системы;
- события можно использовать не только для статистики, но и в будущем — для оптимизации показов (если Telegram внедрит автооптимизацию).