Интеграция Яндекс Метрики и Телеграм: как отслеживать статистику взаимодействия с ботом

Телеграм сейчас не только один из самых популярных мессенджеров, но и важный канал коммуникации с клиентами. Часто Телеграм-бот становится промежуточным шагом на пути пользователя к покупке или основной точкой совершения конверсии. Поэтому важно анализировать, как пользователи взаимодействуют с чат-ботом, чтобы своевременно выявлять и устранять проблемы в их опыте общения.
Собрать полную информацию о пользователе помогает Яндекс Метрика. Она позволяет узнать:
  • откуда пришел на сайт;
  • откуда перешел в чат-бот;
  • как именно взаимодействовал с чат-ботом и т. д.
В этой статье мы разберем:
  • как передавать историю взаимодействия с чат-ботом в Яндекс Метрику;
  • как определить, кто именно перешел к вашему чат-боту в Телеграме;
  • как подготовить скрипт для чат-бота в Телеграме.

Код счетчика Яндекс Метрики невозможно напрямую встроить в чат-бот. Однако для отслеживания действий пользователей можно воспользоваться Measurement Protocol. 
Прежде чем приступать к внедрению Measurement Protocol, необходимо определить, какие действия пользователей чат-бота нужно отслеживать. Для этого стоит представить чат-бот как условный сайт и продумать, каким образом передавать хиты о взаимодействиях пользователя на этом «сайте».
Отслеживать можно следующие типы хитов:
  • просмотры страниц (экраны),
  • события,
  • цели,
  • E-commerce.
Разберем подробнее каждый тип хитов.

В Яндекс Метрике для формирования визита (сессии) требуется хотя бы один хит просмотра страницы. Поэтому в чат-боте при переходе пользователя на первый экран следует отправить хит типа pageview. Каждый экран внутри бота можно рассматривать как аналог веб-страницы.
Пример запроса Measurement Protocol для отправки просмотра страницы:
import requests
import json
import pandas as pd
import pandasql as ps
#——————Для заполнения (начало)
ms = »              #Укажите ваш токен
tid = 88989734                                     #Укажите ваш счетчик
cid = 1710232430899999999                       #Идентификатор ClientID
dr = ‘https://yandex.ru/’                                #Реферер
dl = ‘https://yourdomain.ru/chatbot/main_screen’         #URL
dt = ‘Чат-бот Главный экран’                             #Заголовок страницы
#et = 1728630000                                         #Время хита (Timestamp, если не передан, будет использовано время получения данных)
#——————Для заполнения (конец)
URL = ‘https://mc.yandex.ru/collect/?tid=’+str(tid)+‘&cid=’+str(cid)+‘&t=pageview&dr=’+str(dr)+‘&dl=’+str(dl)+‘&dt=’+str(dt)+‘&ms=’+str(ms)
r_s = requests.get(URL)
print(r_s)

Параметры событий могут быть полезны, чтобы детализировать поведение пользователей в чат-боте:
  • с какими кнопками чаще взаимодействуют;
  • как отвечают на вопросы бота и т.д.
Событиями можно разметить взаимодействия пользователей с навигацией чат-бота и отправку ими сообщений в чат-боте.
Пример Measurement Protocol для отправки событий:
#Отправка событий
import requests
import json
import pandas as pd
import pandasql as ps
#——————Для заполнения (начало)
ms = »              #Укажите ваш токен
tid = 88989734                                           #Укажите ваш cчетчик
cid = 1710232430899999999                                #Идентификатор ClientID
dl = ‘https://yourdomain.ru/test1’                       #URL события 
params = ‘{«clickButton»:»Текст кнопки»}’                #Параметры события
#et = 1728630000                                         #Время хита (Timestamp, если не передан, будет использовано время получения данных)
#——————Для заполнения (конец)
URL = ‘https://mc.yandex.ru/collect/?tid=’+str(tid)+’&cid=’+str(cid)+’&t=event¶ms=’+str(params)+’&dl=’+str(dl)+’&ms=’+str(ms)
r_s = requests.get(URL)
print(r_s)

Цели в Яндекс Метрике можно настроить на основе определенных просмотров страниц либо срабатывания событий.
Пример, как отправить «JavaScript-цель» (цель, срабатывающую по событию) через Measurement Protocol:
import requests
import json
import pandas as pd
import pandasql as ps

#——————Для заполнения (начало)
ms = »              #Укажите ваш токен
tid = 88989734                                     #Укажите ваш счетчик
cid = 1710232430899999999                       #Идентификатор ClientID
dr = ‘https://yourdomain.ru/test1’          #Реферер
ea = ‘test_mp’                                   
#et = 1728630000                #Время хита (Timestamp, если не передан, будет использовано время получения данных)
#——————Для заполнения (конец)

URL = ‘https://mc.yandex.ru/collect/?tid=’+str(tid)+‘&cid=’+str(cid)+‘&t=event&dr=’+str(dr)+‘&ea=’+str(ea)+‘&ms=’+str(ms)

r_s = requests.get(URL)
print(r_s)

Если чат-бот используется для продажи товаров, то для удобного анализа можно передавать в Метрику информацию о товарах, с которыми взаимодействует пользователь:
  • сколько и каких товаров было добавлено в корзину;
  • какие товары просматривал пользователь;
  • какие товары были куплены и т. д.
Пример использования Measurement Protocol для передачи данных о покупке (успешное оформление заказа):
import requests
import json
import pandas as pd
import pandasql as ps
#——————Для заполнения (начало)
ms = »              #Укажите ваш токен
tid = 88989734                                           #Укажите ваш счетчик
cid = 1710232430899999999                                #Идентификатор ClientID
pa = ‘purchase’                                          #ecom действие с товаром (detail, и т.д.)
#et = 1728630000                                         #Время хита (Timestamp, если не передан, будет использовано время получения данных)
#——————Для заполнения (конец)
#список товаров
pr1id = 456
pr1nm = ‘iphone’
pr1br = ‘apple’
pr1pr = 50000
pr2id = 459
pr2nm = ‘airpods’
pr2br = ‘apple’
pr2pr = ‘20000’
URL = ‘https://mc.yandex.ru/collect/?tid=’+str(tid)+‘&cid=’+str(cid)+‘&t=event&pa=’+str(pa)+‘&pr1id=’+str(pr1id)+‘&pr1nm=’+str(pr1nm)+‘&pr1br=’+str(pr1br)+‘&pr1pr=’+str(pr1pr)+‘&pr2id=’+str(pr2id)+‘&pr2nm=’+str(pr2nm)+‘&pr2br=’+str(pr2br)+‘&pr2pr=’+str(pr2pr)+‘&ti=’+str(ti)+‘&tr=’+str(tr)+‘&ms=’+str(ms)
r_s = requests.get(URL)
print(r_s)

Если нужно отслеживать действия внутри чат-бота без привязки к сайту, в качестве clientID можно использовать любой уникальный идентификатор. Например, подойдет ID пользователя в самом Телеграме (бот получает его, когда пользователь нажимает кнопку Start).
Однако чтобы склеить поведение одного и того же человека на сайте и в Телеграм-боте, необходимо передать в бот clientID, присвоенный ему на сайте. Для этого в ссылку на чат-бота добавляется параметр clientID.
Пример ссылки: https://t.me/<название_бота>?start=<clientID>
При переходе по такой ссылке пользователь запускает бота командой /start, передавая параметр clientID. В результате бот получает и этот идентификатор, и данные профиля пользователя из Телеграма.

Для примера разработаем простейший чат-бот для подбора фильмов. Этого будет достаточно, чтобы продемонстрировать отслеживание просмотров экранов и кликов по кнопкам.
import requests
import time
TOKEN = »     #Укажите токен чат-бота в ТГ.
ms = »        #Укажите ваш токен Яндекс Метрики
tid = »       #Укажите ваш cчетчик
cids = {} #clientID
prev = {} #предыдущая страница
URL = f’https://api.telegram.org/bot{TOKEN}/’
last_update_id = 0
user_states = {} 
#———Функции для отправки хитов в Яндекс Метрику (start)
#ОТПРАВКА ПРОСМОТРОВ
def YM_send_pageView(path, dt, chat_id):
    cid = cids.get(chat_id, chat_id)                         #если есть clientID в словаре, то берем его, если нет используем chat_id
    dl = ‘https://yourdomain.ru/chatbot/’+str(path)          #URL
    URL = ‘https://mc.yandex.ru/collect/?tid=’+str(tid)+’&cid=’+str(cid)+’&t=pageview&dl=’+str(dl)+’&dt=’+str(dt)+’&ms=’+str(ms)
    r_s = requests.get(URL)
    print(‘pageView’)
    print(r_s)
#ОТПРАВКА СОБЫТИЙ
def YM_send_event_button(path, button, chat_id):
    cid = cids.get(chat_id, chat_id)                         #если есть clientID в словаре, то берем его, если нет используем chat_id
    dl = ‘https://yourdomain.ru/chatbot/’+str(path)
    URL = ‘https://mc.yandex.ru/collect/?tid=’+str(tid)+’&cid=’+str(cid)+’&t=event¶ms={«clickButton»:»‘+str(button)+'»}&dl=’+str(dl)+’&ms=’+str(ms)
    r_s = requests.get(URL)
    print(‘event’)
    print(r_s)
#———Функции для отправки хитов в Яндекс Метрику (end)
# Главное меню
main_keyboard = {
    «keyboard»: [
        [{«text»: «🎬 Фильмы»}, {«text»: «📺 Сериалы»}],
        [{«text»: «🔍 Поиск по жанру»}, {«text»: «✍️ Оставить отзыв»}],
        [{«text»: «🔥 Топ 10»}, {«text»: «🎲 Случайный»}],
        [{«text»: «📚 Инструкция»}, {«text»: «🔙 Назад в меню»}],
    ],
    «resize_keyboard»: True
}
def send_message(chat_id, text, reply_markup=None):
    payload = {
        «chat_id»: chat_id,
        «text»: text,
        «reply_markup»: reply_markup or main_keyboard
    }
    requests.post(URL + ‘sendMessage’, json=payload)
def handle_command(message):
    user_id = message[«from»][«id»]
    chat_id = message[«chat»][«id»]
    text = message.get(«text», «»)
    # Состояния ввода
    if user_id in user_states:
        state = user_states[user_id]
        if state == «waiting_feedback»:
            send_message(chat_id, f»Спасибо за отзыв!\nТы написал: “{text}”»)
            del user_states[user_id]
            return
        elif state == «waiting_genre»:
            genre = text.lower()
            recommendations = {
                «комедия»: [«Очень страшное кино», «Маска», «1+1»],
                «боевик»: [«Джон Уик», «Терминатор», «Форсаж»],
                «драма»: [«Зеленая миля», «Престиж», «Остров проклятых»]
            }
            films = recommendations.get(genre)
            if films:
                send_message(chat_id, f»Рекомендации в жанре ‘{genre}’:\n- » + «\n- «.join(films))
            else:
                send_message(chat_id, «Жанр не найден. Попробуй: комедия, боевик, драма.»)
            del user_states[user_id]
            return
    # Команды
    if text == «/start»:
        send_message(chat_id, «Привет! Я бот для рекомендаций фильмов и сериалов. Выбери опцию ниже:»)
        path = ‘start’
        dt = ‘Экран приветствия’
        YM_send_pageView(path, dt, chat_id)        
        prev[chat_id] = path
elif text.startswith(«/start») and text[len(«/start»):].lstrip() == text[len(«/start»):].lstrip(» «): #доп условия, чтобы обработать clientID   
        send_message(chat_id, «Привет! Я бот для рекомендаций фильмов и сериалов. Выбери опцию ниже:»)
        client_id = text[len(«/start»):].strip() or None
        cids[chat_id] = client_id        
        path = ‘start’
        dt = ‘Экран приветствия’
        YM_send_pageView(path, dt, chat_id)
        prev[chat_id] = path        
    elif text == «🎬 Фильмы»:        
        button = ‘🎬 Фильмы’
        YM_send_event_button(prev[chat_id], button, chat_id)     
        send_message(chat_id, «Популярные фильмы:\n- Начало\n- Дюна\n- Матрица»)
        path = ‘movies’
        dt = ‘Фильмы’
        YM_send_pageView(path, dt, chat_id)
        prev[chat_id] = path
    elif text == «📺 Сериалы»:
        button = ‘📺 Сериалы’
        YM_send_event_button(prev[chat_id], button, chat_id)
        send_message(chat_id, «Популярные сериалы:\n- Шерлок\n- Во все тяжкие\n- Ведьмак»)
        path = ‘series’
        dt = ‘Сериалы’
        YM_send_pageView(path, dt, chat_id)
        prev[chat_id] = path        
    elif text == «🔥 Топ 10»:        
        button = ‘🔥 Топ 10’
        YM_send_event_button(prev[chat_id], button, chat_id)        
        send_message(chat_id, «Топ 10 IMDb:\n1. Побег из Шоушенка\n2. Крестный отец\n3. Темный рыцарь»)        
        path = ‘top10’
        dt = ‘Топ 10’
        YM_send_pageView(path, dt, chat_id)
        prev[chat_id] = path                
    elif text == «🎲 Случайный»:        
        button = ‘🎲 Случайный’
        YM_send_event_button(prev[chat_id], button, chat_id)        
        import random
        options = [«Интерстеллар», «Драйв», «Платформа», «Остров проклятых»]
        send_message(chat_id, f»Советую посмотреть: {random.choice(options)}»)        
        path = ‘random’
        dt = ‘Случайный’
        YM_send_pageView(path, dt, chat_id)
        prev[chat_id] = path        
    elif text == «📚 Инструкция»:        
        button = ‘📚 Инструкция’
        YM_send_event_button(prev[chat_id], button, chat_id)        
        send_message(chat_id, «Выбирай кнопки для рекомендаций, отправь отзыв или введи жанр.»)        
        path = ‘instructions’
        dt = ‘Инструкция’
        YM_send_pageView(path, dt, chat_id)
        prev[chat_id] = path        
    elif text == «🔍 Поиск по жанру»:        
        button = ‘🔍 Поиск по жанру’
        YM_send_event_button(prev[chat_id], button, chat_id)        
        send_message(chat_id, «Напиши жанр: комедия, боевик, драма.»)
        user_states[user_id] = «waiting_genre»        
        path = ‘search_genre’
        dt = ‘Поиск по жанру’
        YM_send_pageView(path, dt, chat_id)
        prev[chat_id] = path        
    elif text == «✍️ Оставить отзыв»:        
        button = ‘✍️ Оставить отзыв’
        YM_send_event_button(prev[chat_id], button, chat_id)        
        send_message(chat_id, «Пожалуйста, введи свой отзыв:»)
        user_states[user_id] = «waiting_feedback»        
        path = ‘feedback’
        dt = ‘Оставить отзыв’
        YM_send_pageView(path, dt, chat_id)
        prev[chat_id] = path        
    elif text == «🔙 Назад в меню»:        
        button = ‘🔙 Назад в меню’
        YM_send_event_button(prev[chat_id], button, chat_id)        
        send_message(chat_id, «Возвращаемся в меню.»)        
        path = ‘menu’
        dt = ‘меню’
        YM_send_pageView(path, dt, chat_id)
        prev[chat_id] = path        
    else:
        send_message(chat_id, «Не понял сообщение. Используй кнопки или напиши отзыв.»)        
        path = ‘404’
        dt = ‘404’
        YM_send_pageView(path, dt, chat_id)
        prev[chat_id] = path
def poll():
    global last_update_id
    while True:
        try:
            res = requests.get(URL + ‘getUpdates’, params={«offset»: last_update_id + 1, «timeout»: 10})
            data = res.json()
            for update in data[«result»]:
                last_update_id = update[«update_id»]
                if «message» in update:
                    handle_command(update[«message»])
        except Exception as e:
            print(«Ошибка:», e)
            time.sleep(3)
if __name__ == ‘__main__’:
    print(«Бот запущен…»)
    poll()
Ключевыми в реализации отправки данных являются две функции:
  • YM_send_pageView — отправка просмотров страниц;
  • YM_send_event_button — отправка событий нажатия кнопки.
В текущем варианте реализации логика отправки хитов рассчитана на то, что пользователь всегда начинает общение с командой /start (первая активация бота). Если же пользователь регулярно возвращается к боту (не начиная заново через /start), следует усложнить логику. 
Важно, чтобы при каждом новом сеансе первым отправлялся хит просмотра страницы, а уже затем — хит события (клик по кнопке).
В коде используются два вспомогательных словаря: cids и prev.

Когда пользователь переходит по ссылке вида https://t.me/your_bot?start=clientID, значение clientID сохраняется в словаре cids. Далее этот идентификатор передается в Яндекс Метрику при отправке хитов.
clientID — идентификатор пользователя в Яндекс Метрике (хранится в cookie _ym_uid при установленном счетчике на сайте). Передача clientID с сайта в бот позволяет связать действия пользователя на сайте и в чат-боте.
Таким образом, вы сможете проследить полный путь пользователя по воронке: от первых касаний рекламных кампаний до финальных шагов внутри чат-бота. Это поможет в дальнейшем оптимизировать ваши рекламные кампании.

Словарь prev необходим, чтобы в Яндекс Метрике отображалось, какие кнопки нажимал пользователь на том или ином экране.
После нажатия пользователь переходит на новый экран чат-бота. Поэтому URL текущего экрана сохраняется в словаре prev сразу после отправки хита просмотра страницы.
Таким образом, используя совместно сайт, чат-бот и Яндекс Метрику, можно собрать единую картину поведения пользователя. Специалисты по маркетингу и аналитике получат возможность проследить весь путь клиента: от первого визита на сайт до финальных действий в чат-боте. Эти данные помогут качественнее улучшить пользовательский опыт и повысить эффективность рекламных кампаний.
Нужна консультация? Напишите нам на почту analyticspace@adventum.ru или оставьте заявку на сайте.
 
Автор: Сысоев Иван | Analytics Group Head | Adventum

Подпишитесь на полезные материалы, которые помогут вам

Оформляя подписку, вы разрешаете обработку персональных данных и соглашаетесь с  политикой конфиденциальности

backgroundbackground
background
background