Перейти до змісту

Кейс · Аналітика

87 парних днів із 88: перевірка на парність, що викрила подвійний підрахунок реєстрацій у GA4

GA4 кар’єрної платформи показував парну кількість реєстрацій 87 днів із 88. Перевірка за кілька хвилин привела до двох тегів, чотирьох місць у коді та чекліста аудиту наприкінці.

happymonday.ua
Клієнт
happymonday.ua, українська кар’єрна платформа
Моя частина
Аудит GA4 і GTM із Claude Code
Терміни
Знайдено 28 липня · виправлено 29 липня 2026 року
Через місяць
GA4 зафіксував 85% реєстрацій, а розбіжність удалося пояснити

Скарга була коротка. Керівник напряму зростання в клієнта написав, що GA4 бачить ледве 30% реєстрацій. Сайт — happymonday.ua, українська кар’єрна платформа. Реєстрації входять до п’яти показників, які ми домовилися налагодити, і реклама в Google оптимізується за ними.

Я почав не зі звітів, а із сирих даних. Мій агент через GA4 API витягнув кількість подій реєстрації за кожен день із 1 травня до 27 липня — 88 днів. Потім я поставив запитання, яке звучить безглуздо. Скільки із цих чисел парні?

Як парне число видає помилку

Якщо кожну реєстрацію рахувати один раз, денна сума випадково буде парною або непарною. За 88 днів можна очікувати близько 44 парних значень. Якщо кожну реєстрацію рахувати двічі, денна сума завжди буде парною.

87 парних днів із 88 — це приблизно так само ймовірно, як вгадати результат 81 підкидання монети поспіль. Це була не випадковість. Щось надсилало кожну реєстрацію в GA4 двічі.

Події реєстрації в GA4 за день, 1 травня – 27 липня 2026

Звичайна на вигляд крива: вища в будні, нижча у вихідні, один сплеск на початку червня. 87 із 88 денних значень — парні числа; єдине непарне — 18 червня.

Індекс: середній день — 100, округлено до 5. Точка — 18 червня, єдиний непарний день. За формою нічого не видно: подвоєння видно лише в сирих числах, де всі інші дні — парні числа. Джерело: GA4 Data API, happymonday.ua, кількість подій за день

На графіку цього не видно. У будні значення високі, на вихідних низькі, на початку червня є один стрибок. Подвійний підрахунок не змінює форму кривої. Він змінює рівень, а рівень помітний лише в порівнянні із чимось іншим.

Єдиним непарним днем було 18 червня. Я не знаю чому. Можливо, один із двох запитів загубився дорогою. Один непарний день із 88 не змінює висновку, тому я не копав далі.

Ця перевірка працює для будь-якої події, яку ви рахуєте за днями: реєстрацій, покупок, надсилань форми. Вона також працює після виправлення. Коли дублювання зникне, мають з’явитися непарні числа.

Чому GA4 рахував реєстрації двічі

Далі я взявся за контейнер менеджера тегів і код сайту. Claude Code прочитав їх: контейнер — це одне велике вивантаження в JSON, а сайт працює на темі WordPress. Я перевірив його знахідки.

Подію реєстрації слухали два теги. Один чекав саме на цю назву події. Інший пропускав усе: пересилав кожну подію, назва якої починалася з «user» (тригер був ^user.*). Назва події реєстрації починалася з «user». Тому кожна реєстрація потрапляла в GA4 двічі.

Той самий загальний тригер пропускав сміттєву подію, яка спрацьовувала на сторінках авторизованих користувачів і нічого не вимірювала. За місяць таких подій було приблизно по одній на кожні п’ять переглядів сторінок у всьому ресурсі.

У коді теж були проблеми. Він надсилав подію реєстрації із чотирьох місць на різних етапах:

  • Дві події спрацьовували на сторінці «перевірте пошту», ще до того, як людина щось підтвердила.
  • Ще дві спрацьовували після реєстрації через Google, але лише якщо позначка в URL пережила ланцюжок перенаправлень. Часто вона зникала, і таку реєстрацію взагалі не рахували.

Отже, GA4 пропускав значну частину реєстрацій, а решту рахував двічі. За моїми оцінками, навіть «30%» були завищеним показником, але я не міг звірити оцінки з базою даних.

За ті самі кілька днів знайшлося ще більше схожих проблем:

  • Перегляд сторінки позначили як ключову подію, тому кожен перегляд рахувався як конверсія. Ще п’ять ключових подій не працювали.
  • Форма заявки для B2B надсилала власну подію, але жоден тег її не слухав. Заявки B2B ніколи не відстежувалися.
  • Тип користувача — кандидат або компанія — для всіх приходив як «(not set)». Тег надсилав його з кожною подією, а в GA4 його зареєстрували як властивість користувача. Дані B2C і B2B змішувалися.
  • Ідентифікатор користувача був порожнім у кожній події. Код записував userId, тег читав userID, а сам ідентифікатор з’являвся на сторінці вже після спрацювання аналітичного тега.
  • Усередині кнопки, яка веде кандидата на сайт роботодавця, є значок і текст. Тригер кліку реагував лише на саме посилання, тому кліки на значок або текст губилися.

Виправлення: одна реєстрація, одна подія

Основну частину ми виправили за один день — 29 липня.

Спочатку змінили контейнер. Мій агент зібрав файл для імпорту й виконав 29 автоматичних перевірок, зокрема підтвердив, що всі інші теги, тригери та змінні залишилися без змін. Я вручну імпортував файл і опублікував його о другій ночі. Він призупинив дубльований тег і звузив загальний тригер до двох точних назв подій. Також додав тег для форми заявки B2B, переніс тип користувача туди, де його очікував GA4, і почав рахувати клік у будь-якій точці кнопки переходу на сайт роботодавця.

Потім — код. Я написав завдання на одну сторінку, і команда клієнта випустила зміни того самого дня. Усі п’ять старих надсилань прибрали — п’яте надсилало подію з іншою назвою. Замість них залишилася одна подія, а сервер вирішує, коли її надсилати: один раз для кожного нового користувача, на першій сторінці, яку він бачить із підтвердженим профілем. Потім сервер позначає цього користувача в базі даних, тому подія не може спрацювати двічі. Спосіб реєстрації — через електронну пошту або Google — і тип користувача передаються як параметри цієї події.

У GA4 перегляд сторінки та п’ять мертвих подій перестали бути ключовими. Нові події отримали цю позначку.

До

Подія надходить із 4 місць→ 2 теги пересилають кожну подію→ Пораховано двічі або втрачено

Після

Профіль підтверджено→ Сервер надсилає 1 подію→ Користувача позначено: більше ніколи→ 1 тег → GA4
Раніше два із чотирьох місць надсилали подію ще до підтвердження електронної пошти, а ще два залежали від того, чи переживе позначка в URL перенаправлення. Тепер сервер вирішує й запам’ятовує.

Одна деталь стане важливою пізніше. Подія досі проходить через браузер, тому блокувальник реклами може її зупинити. Але тепер сервер точно знає, для кого він надіслав подію. Тому фраза «GA4 показує менше, ніж база даних» перетворюється з припущення на арифметику.

Перший доказ з’явився наступного дня: години з непарною кількістю реєстрацій. За дублювання такого бути не може. Кандидати й компанії вперше відображалися окремо, а реєстрації через Google приходили зі способом реєстрації.

Один крок запізнився. Ціль реєстрації в рекламі Google була побудована на старій події. Імпорт нової події в рекламу був у списку справ, але його зробили майже через два тижні, а доти ціль показувала нуль. Якщо змінюєте подію, того самого дня перемикайте все, що її читає.

GA4 проти бази даних: куди зникають інші 15%

Через місяць я порівняв GA4 з базою даних сайту за кожним показником за 1–30 серпня. Тут база даних — джерело правди: відгук на вакансію — це рядок, реєстрація — користувач.

Яку частку реальних дій записав GA4, серпень 2026

Порівняно з базою сайту: відгуки 94%, переходи на сайт роботодавця 92%, реєстрації 85%, реєстрації компаній 83%, B2B-заявки 100%.

1–30 серпня. Реєстрацій компаній і заявок мало, тож їхні частки можуть стрибати від місяця до місяця. Джерело: GA4 Data API і база сайту, звірка 31 серпня 2026

GA4 ніколи не збігатиметься з базою даних до останнього числа. Корисніше запитати, чи стабільна різниця. Помилка спричиняє стрибки. Стабільна різниця — це нормальні втрати на боці відвідувача: блокувальники реклами й вкладки, закриті до того, як запит устиг піти.

День за днем GA4 фіксував 94% відгуків на вакансії з похибкою 2,2 відсоткового пункта протягом усіх 30 днів. У липні було так само. Найчистіший доказ дають переходи на сайти роботодавців. Сайт записує кожен такий клік власним запитом до власного домену, а запит GA4 спрацьовує під час того самого кліку. Один клік, два записи. Блокувальники відсікають лише запис GA4.

Для реєстрацій різниця більша, і тут допомагає серверна позначка. Я зміг точно розкласти ці 15%, а не вгадувати.

Куди зникають 15% реєстрацій

З усіх реєстрацій у базі сайт надіслав подію для 95%, а GA4 записав 85%.

Кожна смуга — частка від усіх реєстрацій у базі. Джерело: happymonday.ua, 1–30 серпня 2026: база, власна позначка сайту і GA4
  • Для 5% реєстрацій подія не спрацьовує за задумом. Більшість із них — 4,5% усіх реєстрацій — це люди, які реєструються через електронну пошту, але не підтверджують її або більше не повертаються авторизованими. Це також список людей, яким клієнт може нагадати про реєстрацію.
  • Ще для 10% сайт надіслав подію, але вона не дійшла. Це 10,5% усіх надісланих сайтом подій — такі самі втрати, як і всюди.

Правила для звітів стали простими. Обсяги беремо з бази даних. Джерела, поведінку й воронки — з GA4, пам’ятаючи про коефіцієнт близько 0,9.

Тепер щотижня ми звіряємо частку надісланих подій реєстрації, які доходять до GA4 — у серпні це було 89,5% — із заздалегідь визначеними порогами: 84% або більше — шум, 80% або менше — треба дивитися уважніше. У середині вересня показник на тиждень упав до 77%, найсильніше для реєстрацій через сторінку опитування. Він повернувся до 91% у день, коли команда прискорила завантаження скриптів сайту. Це лише збіг у часі, а не доказ. Але щотижнева перевірка виявила падіння, поки воно тривало.

І дублювання зникло. За місяць даних лише один користувач отримав подію реєстрації двічі.

Через два місяці: ще три зламані події

Наприкінці вересня ми перевірили всі 38 назв подій, які GA4 отримав після виправлення. З реєстраціями все було добре. Із трьома іншими подіями — ні:

  • «Оплата вакансії» була кліком на кнопку «Опублікувати» у формі вакансії, включно з редагуваннями. Вона показувала приблизно в 15 разів більше «оплат», ніж було оплачених замовлень, а сума оплати в кожній події була порожньою.
  • «Купівля гайда» спрацьовувала на будь-якій сторінці подяки після оплати. 84% цих «покупок» були оплатами за публікацію вакансій, а перезавантаження сторінки рахувало одне замовлення до семи разів.
  • Підписки на сповіщення про вакансії не рахувалися рік. Тег чекав на кнопку зі старим текстом і старим оформленням. Сайт змінив і те, і інше, а тег далі чекав.

Ці зміни потребують більше обережності, ніж здається. Дві з подій — ключові, а GA4 передає дані в рекламу клієнта в Google. Змінюючи ключову подію, ви змінюєте те, за чим оптимізуються кампанії, і втрачаєте порівняння з минулим. Тому ми додаємо нові правильні події поруч зі старими: оплату рахуємо на сторінці успішної оплати, один раз на номер замовлення. Два тижні даних, звірка з базою — і лише потім перемикання. На початок жовтня цей пакет готовий і чекає на погодження.

Ті самі помилки на моїх сайтах

Усе це трапляється не лише на великих сайтах. На малих у мене були ті самі помилки.

На plants.place мій ШІ-агент повідомив, що події працюють. Коли я спитав, чи справді надходять дані, він перевірив ще раз. Події потрапляли до рівня даних сторінки, але жоден тригер у контейнері їх не підхоплював. Виправляючи це, агент налаштував сім тегів з ідентифікатором вимірювання GA4, який увів вручну. Ідентифікатор був неправильним. Агент сам це помітив. Якби ні, ніхто б не поскаржився: теги спрацьовують, запити йдуть, дані не потрапляють нікуди. Тепер ідентифікатор завжди надходить з API.

У невеликій мережі моїх контентних сайтів GA4 рахував приблизно вп’ятеро менше вихідних кліків, ніж партнерські програми на іншому боці. Тепер я рахую ці кліки на власному перенаправленні, якого блокувальник не бачить.

Чекліст аудиту GA4

Кожен пункт з’явився через реальну помилку із цієї історії. Почніть із першого — він потребує кількох хвилин.

ПеревіркаЩо робитиПомилка, через яку з’явився пункт
Парні значенняПорахуйте подію за днями. Якщо майже щодня число парне, подію надсилають двічі.87 парних днів із 88. Два теги пересилали кожну реєстрацію.
Тригери за шаблономЗнайдіть тригери, які зіставляють назви подій за шаблоном, і складіть список того, що вони пропускають.«Будь-яка подія, що починається з user» створювала другу копію кожної реєстрації та пропускала сміттєву подію.
Події без тегівДля кожної події, яку надсилає сайт, знайдіть її тег. Для кожного тега перевірте, чи спрацьовував він за останні 30 днів.Форма заявки B2B надсилала подію, яку не слухав жоден тег. Тег підписки чекав на кнопку, яка змінилася: рік нульових значень.
Ключові подіїКожна ключова подія — це результат, а не перегляд чи клік.Перегляд сторінки був ключовою подією. «Оплата вакансії» була кліком на кнопку — приблизно в 15 разів більше за реальну кількість оплат.
ПокупкиПодія покупки спрацьовує один раз на замовлення для одного товару.«Купівля гайда» спрацьовувала на кожній сторінці подяки: 84% були іншими оплатами, а перезавантаження рахували одне замовлення до семи разів.
Момент спрацюванняПодія спрацьовує після результату, а не до нього.Реєстрація спрацьовувала на сторінці «перевірте пошту», перш ніж користувач щось підтвердив.
ПеренаправленняПодія переживає перенаправлення, зокрема під час входу через Google.Реєстрації через Google залежали від того, чи переживе позначка в URL ланцюжок перенаправлень. Часто вона зникала.
Порожні значенняПеревірте частку «(not set)» та порожніх значень у параметрах, за якими будуєте звіти.Тип користувача для всіх був «(not set)» через неправильну область дії. Ідентифікатор користувача був порожнім у кожній події: userId проти userID.
Область клікуТригер кліку має ловити кліки на значок і текст всередині кнопки.Кліки на значок усередині кнопки переходу на сайт роботодавця губилися.
Ідентифікатор вимірюванняНадішліть тестову подію й перевірте, чи вона надійшла. Беріть ідентифікатор з API, а не з пам’яті.На моєму сайті події доходили до рівня даних, але жоден тригер їх не підхоплював, а ідентифікатор у семи нових тегах увели вручну й помилилися.
Другий підрахунокПорівнюйте з базою даних або з підрахунком партнера — за днями, як співвідношення. Стабільність означає втрати. Стрибки — помилку.GA4 бачить 94% відгуків із похибкою 2,2 відсоткового пункта на день. На моїх сайтах він бачив приблизно вп’ятеро менше кліків, ніж партнери.
Що читає подіюПерш ніж замінювати подію, знайдіть усе, що її імпортує, і перемкніть того самого дня.Після виправлення ціль реєстрації в рекламі Google майже два тижні показувала нуль.
Завершені дніОцінюйте вчорашній день, а не сьогоднішній.GA4 Data API відстає на кілька годин. Одного разу через це ми вирішили, що події перестали надходити. Насправді ні.

Чого я не можу довести

  • Чому 18 червня було непарним. Один день не змінює висновку, тому я не розслідував.
  • З чого саме складаються ці 10,5%. Зазвичай це пояснюють блокувальниками реклами й надто рано закритими вкладками, і стабільне денне співвідношення з цим узгоджується. Я не розділяв втрати за причинами.
  • Що частки B2B залишаться такими самими. Реєстрацій компаній і заявок небагато. Під час вересневої перевірки заявки трималися близько 100%; реєстрації компаній я повторно не перевіряв.
  • Скільки реєстрацій GA4 фіксував до виправлення. У мене є оцінки, але жодну з них я не міг звірити з базою даних за ті самі дні, тому не наводжу цифру.

Що я зробив би інакше

  • Перемкнув би все, що читає подію, того самого дня, коли змінив подію. Тоді ціль у рекламі Google не залишилася б сліпою майже на два тижні.
  • Звірив би кожну ключову подію із другим джерелом даних, а не лише п’ять показників, які ми домовилися виправити. Події оплати й купівлі гайда були неправильними, але ніхто не перевіряв, бо їх не було в списку.
  • Спочатку перевірив би парність, ще до відкриття будь-якого звіту. Це забрало кілька хвилин і відразу вказало на причину.