Нативная интеграция Hotjar с HubSpot отправляет данные о сессиях только в Contact Timeline - не в карточку сделки. Менеджер по продажам, открывающий Deal, не видит ни записей экрана, ни данных о поведении потенциального покупателя. Чтобы сессии появились именно в Deal Timeline, нужна кастомная интеграция через HubSpot Timeline Events API или Engagements API.
Эта статья объясняет, почему так устроена нативная интеграция, что конкретно теряет отдел продаж, и как построить правильный pipeline: от захвата recording URL на стороне Hotjar до создания события в карточке конкретной сделки.
В проектах по настройке HubSpot мы видим одну и ту же картину: команда маркетинга радуется, что Hotjar «подключён к CRM», а sales-менеджер при этом вручную ищет сессии в отдельном интерфейсе Hotjar по email-адресу лида. Данные есть, но они недоступны там, где принимается решение о закрытии сделки.
Что даёт нативная интеграция Hotjar с HubSpot - и чего она не даёт
Нативная интеграция Hotjar + HubSpot - это подключение через маркетплейс HubSpot, которое устанавливается в несколько кликов и не требует кода.
По состоянию на Q2 2026, нативная интеграция умеет:
- Отправлять данные сессий (duration, rage-clicks, u-turns, referrer URL) в Contact Timeline в HubSpot
- Передавать ответы на Hotjar-опросы в Contact Timeline
- Создавать списки контактов на основе Hotjar-свойств (например, «провёл более 5 минут на странице pricing»)
- Триггерить HubSpot-автоматизации на основе Hotjar-событий
Но нативная интеграция не умеет:
- Отправлять данные в Deal Timeline - только в Contact Timeline
- Передавать прямые ссылки на конкретные recording URL в HubSpot
- Привязывать поведенческие данные к конкретной сделке, а не к контакту
- Поддерживать User Attributes Hotjar - атрибуты пользователя не передаются в HubSpot
Это принципиальное ограничение архитектуры: Hotjar работает с понятием «посетитель» (visitor/contact), а менеджер по продажам работает с понятием «сделка» (deal). Нативная интеграция эту связь не устанавливает.
Почему данные сессий не попадают в Deal Timeline
Дело не в «недоработке» интеграции - это следствие разных моделей данных.
Hotjar идентифицирует пользователя по email или visitor ID. Когда посетитель оставляет форму или проходит опрос, Hotjar отправляет событие в HubSpot и связывает его с Contact-объектом по email.
HubSpot-сделка - это отдельный объект в CRM, связанный с Contact через ассоциацию. Нативная интеграция Hotjar не знает о существовании конкретной сделки и не умеет устанавливать ассоциацию «событие -> сделка».
Дополнительно: Hotjar передаёт данные через контактные свойства (contact properties) и Timeline Events для объекта Contact. HubSpot Timeline Events API позволяет создавать события на объектах Contact, Company, Deal или Ticket - но нативная интеграция Hotjar использует только Contact.
Поэтому даже если сессия успешно записана в Contact Timeline, менеджер в карточке Deal её не видит: он должен выйти из Deal, открыть связанный Contact, найти вкладку Activity, и уже там искать Hotjar-события. На практике этого никто не делает.
Что конкретно теряет команда продаж
Представьте типичный сценарий: лид посетил страницу ценообразования четыре раза за неделю, потратил 8 минут на enterprise-тариф, прошёл Hotjar-опрос «что вас останавливает от покупки» и написал «слишком дорого для старта». Менеджер звонит лиду, не видя этого контекста, и начинает разговор стандартным скриптом.
Потери конкретны:
- Контекст перед звонком - менеджер не знает, какие страницы смотрел лид и сколько времени провёл
- Сигналы готовности к покупке - посещение pricing page 4 раза за неделю - это сильный buying signal, который нигде не виден в Deal
- Данные для квалификации - enterprise-поведение (изучение детальных условий, FAQ, security docs) отличается от SMB-поведения, и это видно в записях
- Контекст для передачи сделки - когда SDR передаёт сделку AE, поведенческий контекст теряется полностью
В типовом B2B-пайплайне с циклом продаж 30-90 дней и несколькими стейкхолдерами этот контекст критичен. Похожая проблема возникает и с другими инструментами: например, нативная интеграция HubSpot + Zoom тоже не привязывает записи встреч к конкретной сделке.
Правильный подход - кастомная интеграция
Цель: каждый раз, когда Hotjar фиксирует значимое поведение идентифицированного пользователя, в Deal Timeline этого пользователя автоматически появляется запись со ссылкой на Hotjar-сессию.
Захват recording URL на стороне Hotjar
Hotjar не предоставляет recording URL в реальном времени через webhook. Обходной путь - использовать Hotjar Identify API для передачи пользовательских атрибутов, которые затем можно использовать для фильтрации записей.
Для захвата ссылки на сессию применяется другой подход: Hotjar формирует recording URL в формате https://insights.hotjar.com/sites/{site_id}/sessions/{session_id}. Session ID доступен через cookie _hjSessionUser_{site_id} или через Hotjar JS API.
При идентификации пользователя передайте его email и контекст в Hotjar:
// Идентификация пользователя в Hotjar
window.hj('identify', userId, {
email: userEmail,
plan: 'enterprise',
deal_stage: 'demo_scheduled'
});
// Захват session ID из cookie для формирования recording URL
function getHotjarSessionId(siteId) {
const cookieName = `_hjSessionUser_${siteId}`;
const cookies = document.cookie.split(';');
for (let c of cookies) {
const [name, value] = c.trim().split('=');
if (name === cookieName) {
try {
const parsed = JSON.parse(decodeURIComponent(value));
return parsed.userId; // Это visitor ID, используется в URL записи
} catch (e) { return null; }
}
}
return null;
}
// Фиксация значимого события с передачей в бэкенд
function trackKeyBehavior(eventName, pageUrl, siteId) {
const visitorId = getHotjarSessionId(siteId);
const recordingUrl = visitorId
? `https://insights.hotjar.com/sites/${siteId}/sessions?filters=visitor_id:${visitorId}`
: null;
fetch('/api/crm/hotjar-event', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: window.__userEmail, // email идентифицированного пользователя
event: eventName,
page: pageUrl,
hotjar_url: recordingUrl,
timestamp: new Date().toISOString()
})
});
}
// Пример: фиксация посещения страницы pricing
if (window.location.pathname.includes('/pricing')) {
trackKeyBehavior('pricing_page_visited', window.location.href, YOUR_SITE_ID);
}
Для событий на основе опросов Hotjar поддерживает webhook: при сабмите опроса отправляется POST-запрос с email пользователя и ответами. Это более надёжный trigger для создания записи в CRM.
Timeline Event в HubSpot Deal через Timeline Events API
HubSpot Timeline Events API позволяет создавать кастомные события на объектах Contact, Company, Deal или Ticket. Событие отображается в Activity Timeline объекта.
Для создания события на Deal нужно:
- Создать Event Template через API или UI (Settings -> Integrations -> Private Apps)
- При создании шаблона указать
objectType: DEAL - Отправлять события через
POST https://api.hubapi.com/crm/v3/timeline/events
Альтернативный подход, который не требует предварительного создания шаблона - создать Note через Engagements API и привязать её к Deal:
import requests
import json
from datetime import datetime
HUBSPOT_TOKEN = "your_private_app_token"
BASE_URL = "https://api.hubspot.com"
headers = {
"Authorization": f"Bearer {HUBSPOT_TOKEN}",
"Content-Type": "application/json"
}
def find_deal_by_contact_email(email: str) -> str | None:
"""Найти активную сделку по email контакта."""
# Шаг 1: найти контакт
search_payload = {
"filterGroups": [{
"filters": [{
"propertyName": "email",
"operator": "EQ",
"value": email
}]
}],
"properties": ["email", "hs_object_id"]
}
r = requests.post(
f"{BASE_URL}/crm/v3/objects/contacts/search",
headers=headers,
json=search_payload
)
contacts = r.json().get("results", [])
if not contacts:
return None
contact_id = contacts[0]["id"]
# Шаг 2: получить ассоциированные сделки
r = requests.get(
f"{BASE_URL}/crm/v4/objects/contacts/{contact_id}/associations/deals",
headers=headers
)
associations = r.json().get("results", [])
if not associations:
return None
# Возвращаем первую активную сделку
return associations[0]["toObjectId"]
def create_hotjar_note_on_deal(
deal_id: str,
contact_id: str,
hotjar_url: str,
event_name: str,
page_url: str
) -> dict:
"""Создать заметку с ссылкой на Hotjar-сессию в Deal Timeline."""
note_body = (
f"Hotjar session: {event_name}\n"
f"Page: {page_url}\n"
f"Recording: {hotjar_url}"
)
payload = {
"properties": {
"hs_note_body": note_body,
"hs_timestamp": datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
},
"associations": [
{
"to": {"id": deal_id},
"types": [{
"associationCategory": "HUBSPOT_DEFINED",
"associationTypeId": 214 # Note -> Deal
}]
},
{
"to": {"id": contact_id},
"types": [{
"associationCategory": "HUBSPOT_DEFINED",
"associationTypeId": 202 # Note -> Contact
}]
}
]
}
r = requests.post(
f"{BASE_URL}/crm/v3/objects/notes",
headers=headers,
json=payload
)
return r.json()
def handle_hotjar_event(event_data: dict):
"""Обработчик входящего события от Hotjar."""
email = event_data.get("email")
if not email:
return {"error": "no email"}
deal_id = find_deal_by_contact_email(email)
if not deal_id:
return {"error": "no deal found"}
# Получить contact_id для ассоциации
r = requests.post(
f"{BASE_URL}/crm/v3/objects/contacts/search",
headers=headers,
json={
"filterGroups": [{"filters": [{"propertyName": "email", "operator": "EQ", "value": email}]}]
}
)
contact_id = r.json()["results"][0]["id"]
result = create_hotjar_note_on_deal(
deal_id=deal_id,
contact_id=contact_id,
hotjar_url=event_data.get("hotjar_url", ""),
event_name=event_data.get("event", "session"),
page_url=event_data.get("page", "")
)
return result
Аутентификация: Private App Token, создаётся в Settings -> Integrations -> Private Apps. Требуемые скоупы: crm.objects.notes.write, crm.objects.deals.read, crm.objects.contacts.read.
Привязка к конкретной сделке, а не контакту
Ключевой момент: один контакт может быть связан с несколькими сделками. Логика выбора сделки для привязки события:
- По стадии: выбирать сделку в активной стадии (не
closedwon, неclosedlost) - По дате создания: брать самую последнюю открытую сделку
- По кастомному полю: передавать
deal_idявно из фронтенда, если он известен
Для B2B-сценариев с длинным циклом продаж рекомендуется третий вариант: при идентификации пользователя на сайте передавать deal_id через Hotjar Identify API, если пользователь авторизован в продукте или перешёл по персонализированной ссылке.
Аналогичная проблема с привязкой данных к сделке (а не к контакту) существует и в нативной интеграции HubSpot + Intercom, и в HubSpot + Slack - нативные коннекторы работают на уровне контакта, а не сделки.
Реальный кейс: что изменилось после интеграции
В одном из проектов для B2B SaaS-компании (команда продаж 8 человек, средний цикл сделки 45 дней, чек $12,000-40,000) мы построили этот pipeline за три недели.
До интеграции: менеджеры иногда открывали Hotjar вручную, но делали это в лучшем случае перед 20-30% демо-звонков. Для поиска нужной сессии по email уходило 5-10 минут.
После интеграции в каждой карточке Deal автоматически появляются:
- Заметки при каждом посещении страниц pricing, features, security
- Ссылки на Hotjar-сессии с указанием длительности и триггерных событий (rage-click, u-turn)
- Ответы на exit-опросы с привязкой к дате посещения
Результат за первые два месяца:
- Средняя подготовка к демо сократилась с 25 до 8 минут
- Менеджеры стали упоминать конкретные страницы и возражения из Hotjar-сессий в 60% звонков
- Конверсия демо -> коммерческое предложение выросла на 18% - команда связывает это в том числе с лучшим пониманием контекста лида
Если вы строите аналитику продаж, которая замыкает поведение на сайте с CRM-данными, посмотрите на Prooflytics - платформу, которая собирает multi-touch атрибуцию из рекламных кабинетов, CRM и поведения на сайте в единый дашборд.
Для кого это актуально
Эта интеграция нужна командам, у которых одновременно выполняются несколько условий:
- B2B-продукт с циклом продаж от 2 недель и чеком от $3,000-5,000
- На сайте есть значимые страницы (pricing, enterprise features, case studies), которые лиды изучают до покупки
- Hotjar уже установлен и дает реальные сессии идентифицированных пользователей
- Sales-команда работает в HubSpot Deal - именно там принимаются решения о следующем шаге
- SDR/AE-модель: данные о поведении лида нужно передавать вместе со сделкой
Для e-commerce и PLG-продуктов (где нет активной роли продавца) нативной интеграции Hotjar с HubSpot обычно достаточно - там важнее Contact Timeline для маркетинговых автоматизаций.
Аналогичный кастомный подход применяется и для Kommo CRM, когда нужно привязать поведенческие данные именно к воронке продаж, а не к контакту.
Часто задаваемые вопросы
Hotjar говорит, что интеграция с HubSpot включает «session recordings в Contact Timeline» - это значит, что они попадают в Deal?
Нет. Contact Timeline и Deal Timeline - это разные объекты в HubSpot. Данные, которые Hotjar отправляет в Contact Timeline, видны в карточке контакта на вкладке Activity. Чтобы их увидеть из карточки Deal, нужно перейти в связанный Contact - это неудобно и на практике не делается. Нативная интеграция не создаёт события в Deal Timeline.
Можно ли использовать HubSpot Workflow для перемещения Hotjar-событий из Contact в Deal?
Частично. HubSpot Workflow позволяет копировать значения контактных свойств в свойства сделки. Но Hotjar-события - это Timeline Events, а не свойства контакта. Timeline Events нельзя «скопировать» в сделку через Workflow. Можно создать кастомное свойство контакта «Last Hotjar Session URL» и через Workflow копировать его значение в свойство сделки - это более простое решение, хотя и не даёт полной истории событий в Deal Timeline.
Нужен ли для кастомной интеграции отдельный сервер?
Да, нужен backend-сервис, который принимает события с фронтенда (или Hotjar webhook) и делает вызовы к HubSpot API. Это может быть небольшой FastAPI или Express сервис на любом хостинге. Альтернатива - AWS Lambda или Cloudflare Workers для serverless-архитектуры. Бессерверный вариант проще в поддержке для команд без DevOps-ресурса.
Hotjar Events API vs webhook - что выбрать для триггера?
Hotjar webhook (доступен при survey submission) - более надёжный триггер, потому что работает на стороне сервера и не зависит от браузера пользователя. JS Events API на фронтенде может теряться при закрытии вкладки или сетевых ошибках. Для production-интеграции рекомендуется комбинация: JS-события для поведенческих триггеров (посещение pricing, время на странице) + Hotjar webhook для опросов.
Как обрабатывать случай, когда у контакта несколько открытых сделок?
Лучший подход - передавать deal_id явно из фронтенда, если он известен (например, пользователь авторизован в продукте и его сделка известна). Если deal_id неизвестен, выбирать сделку по дате последнего изменения среди активных стадий. При множестве сделок создавать события во всех активных - это безопаснее, чем потенциально потерять событие.
Что делать дальше
- Нативная интеграция Hotjar + HubSpot работает только на уровне Contact Timeline
- Deal Timeline требует отдельного pipeline: захват события на фронтенде -> backend -> HubSpot Notes API с ассоциацией к сделке
- Hotjar Identify API и JS-события дают нужные данные, включая ссылки на сессии
- HubSpot Notes API с
associationTypeId: 214создаёт заметку, видимую в Deal Timeline
Если вы используете HubSpot с Hotjar и хотите, чтобы менеджеры по продажам видели поведение лидов прямо в карточке сделки - опишите вашу ситуацию команде Exceltic.dev. Разберём стек, определим правильную архитектуру привязки событий к сделкам и оценим объём работ.