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

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

Собрать полную информацию о пользователе помогает Яндекс Метрика. Она позволяет узнать:

  • откуда пришел на сайт;
  • откуда перешел в чат-бот;
  • как именно взаимодействовал с чат-ботом и т. д.

В этой статье мы разберем:

  • как передавать историю взаимодействия с чат-ботом в Яндекс Метрику;
  • как определить, кто именно перешел к вашему чат-боту в Телеграме;
  • как подготовить скрипт для чат-бота в Телеграме.

Как передавать историю взаимодействия с чат-ботом в Яндекс Метрику

Код счетчика Яндекс Метрики невозможно напрямую встроить в чат-бот. Однако для отслеживания действий пользователей можно воспользоваться 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&params=’+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)

 

E-commerce (опциональный хит)

Если чат-бот используется для продажи товаров, то для удобного анализа можно передавать в Метрику информацию о товарах, с которыми взаимодействует пользователь:

  • сколько и каких товаров было добавлено в корзину;
  • какие товары просматривал пользователь;
  • какие товары были куплены и т. д.

Пример использования 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. В результате бот получает и этот идентификатор, и данные профиля пользователя из Телеграма.

Пример кода чат-бота в Телеграме

Для примера разработаем простейший чат-бот для подбора фильмов. Этого будет достаточно, чтобы продемонстрировать отслеживание просмотров экранов и кликов по кнопкам.

{{КОД1}}

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&params={«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.

cids

Когда пользователь переходит по ссылке вида https://t.me/your_bot?start=clientID, значение clientID сохраняется в словаре cids. Далее этот идентификатор передается в Яндекс Метрику при отправке хитов.

clientID — идентификатор пользователя в Яндекс Метрике (хранится в cookie _ym_uid при установленном счетчике на сайте). Передача clientID с сайта в бот позволяет связать действия пользователя на сайте и в чат-боте.

Таким образом, вы сможете проследить полный путь пользователя по воронке: от первых касаний рекламных кампаний до финальных шагов внутри чат-бота. Это поможет в дальнейшем оптимизировать ваши рекламные кампании.

prev

Словарь prev необходим, чтобы в Яндекс Метрике отображалось, какие кнопки нажимал пользователь на том или ином экране.

После нажатия пользователь переходит на новый экран чат-бота. Поэтому URL текущего экрана сохраняется в словаре prev сразу после отправки хита просмотра страницы.

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

Нужна консультация? Напишите нам на почту analyticspace@adventum.ru или оставьте заявку на сайте.

Автор: Сысоев Иван | Analytics Group Head | Adventum