Відкритий код
Один event_id для браузера й вашого сервера
ad-events — невелика бібліотека TypeScript, яку ми виділили з власної системи вимірювання LoomaScale. Вона створює один ідентифікатор дедуплікації на конверсію й передає те саме значення до Meta Pixel, Google Ads, пікселя ChatGPT Ads і до їхніх серверних Conversions API — тому конверсія, про яку повідомили двічі, рахується один раз.
- Жодних залежностей
- TypeScript, ESM і CJS
- Node, Bun, Deno і Edge
Чому конверсії рахуються двічі
Вимірювання лише в браузері втрачає від п'ятої частини до третини конверсій через блокувальники реклами та обмеження приватності в браузерах, тому звична відповідь — надсилати ті самі конверсії ще раз із сервера. Зробіть це без спільного ідентифікатора, і про кожну покупку буде повідомлено двічі: ваш дохід у звітах завищений, вартість конверсії виглядає кращою, ніж вона є, а автоматичні стратегії ставок оптимізуються під число, якого ніколи не існувало.
Кожна платформа підтримує це рішення — і кожна називає його по-своєму. Meta очікує eventID у четвертому аргументі виклику пікселя й event_id усередині серверної події. Піксель ChatGPT Ads очікує event_id в аргументі опцій, а суму — цілим числом у центах, а не десятковим дробом. У Google Ads пари «браузер плюс сервер» немає взагалі: він дедуплікує за transaction_id. Помилитеся в одному з них — і ніщо не зламається: ви дізнаєтеся про це за кілька тижнів, із витрат.
Як працює бібліотека
Один виклик повідомляє про конверсію всім налаштованим платформам і повертає використаний ідентифікатор, щоб ви могли передати його на власний бекенд у тому самому обробнику кліку.
1Ідентифікатор створює браузер
Саме браузер, бо це та сторона, яка може не повідомити зовсім. Створіть ідентифікатор там, де відбувається клік, і серверна подія залишиться придатною до дедуплікації навіть тоді, коли блокувальник з'їв піксель — а це і є той випадок, для якого ви додавали серверну подію.
2Кожен адаптер отримує те саме значення
Адаптери Meta, Google Ads і ChatGPT Ads кладуть його туди, де його очікує їхня платформа, і переводять суму в потрібну одиницю. Адаптер, чий піксель не завантажився, просто нічого не робить і не кидає винятку — тому невдале повідомлення ніколи не зламає оформлення замовлення.
3Сервер повторює його
Коли надходить вебхук про оплату — єдине справжнє підтвердження, що гроші прийшли, — сервер надсилає ту саму назву події й той самий ідентифікатор. Платформа розпізнає пару й залишає одну конверсію.
import {
createTracker,
metaAdapter,
googleAdsAdapter,
openAiAdapter,
} from "ad-events/browser";
const tracker = createTracker({
adapters: [
metaAdapter({ eventNames: { checkout_started: "InitiateCheckout" } }),
googleAdsAdapter({
conversionId: "AW-123456789",
labels: { checkout_started: "abcDEF_ghi" },
}),
openAiAdapter(),
],
});
// One id, every platform — and it is the return value, so you
// cannot forget to send it to your own backend.
const eventId = tracker.track({
name: "checkout_started",
value: 49,
currency: "USD",
});
await fetch("/api/checkout", {
method: "POST",
body: JSON.stringify({ plan, price, eventId }),
});import { createMetaConversionsApi } from "ad-events/server";
const meta = createMetaConversionsApi({
pixelId: process.env.META_PIXEL_ID,
accessToken: process.env.META_ACCESS_TOKEN,
});
await meta.send({
eventName: "InitiateCheckout", // identical to the browser event
eventId, // the id the browser minted
email: order.email, // normalized and hashed for you
fbp, fbc, // the cookies the browser read
customData: { value: order.price, currency: "USD" },
});Що вона охоплює
Meta Pixel і Conversions API
Спільний event_id, куки _fbp і _fbc, прочитані в браузері, щоб їх несла серверна подія, а також поля ідентичності, нормалізовані та захешовані SHA-256 так само, як їх хешує Meta під час зіставлення. Ваш власний ідентифікатор користувача хешується перед надсиланням і ніколи не йде у відкритому вигляді.
Google Ads
Конверсії через gtag із дедуплікацією за transaction_id, синхронний незворотний ключ, щоб та сама реєстрація, про яку повідомили дві сторінки повернення, рахувалася один раз, і клік-ідентифікатори gclid, gbraid і wbraid як одне значення замість трьох порожніх стовпців.
ChatGPT Ads (OpenAI)
Піксель oaiq і Conversions API від OpenAI, разом із двома речами, у яких легко помилитися: сума цілим числом у центах і тип корисного навантаження, який не випливає з назви події. Публічних інструментів для цієї платформи поки майже немає.
Атрибуція за першим дотиком, бо воронка живе довше за URL
Реклама приводить людину на URL із параметрами utm і клік-ідентифікатором. Далі відвідувач робить три переходи й платить через два дні — на той момент цих параметрів давно немає, а URL повернення від платіжного сервісу охоче перезапише їх своїми.
Бібліотека знімає їх один раз, зберігає перший дотик і читає їх назад, коли конверсія нарешті настає. Вона також відповідає на питання, яке насправді ставить воронка холодного трафіку: цей відвідувач прийшов із платної реклами? Для платних соцмереж мають збігтися і джерело, і канал; клік-ідентифікатор Google є доказом сам собою, бо Google додає його лише до кліку, за який взяв плату.
Питання
Чи замінює ad-events Google Tag Manager?
Ні. Вона замінює написаний руками зв'язувальний код, який ви інакше поклали б у менеджер тегів або у свій застосунок, щоб ідентифікатори збігалися між платформами. Власні фрагменти пікселів ви завантажуєте самі.
Чому ідентифікатор має створювати браузер, а не сервер?
Бо браузер — це та сторона, яка може не повідомити зовсім. Якщо ідентифікатор створює сервер, то заблокований піксель означає, що браузерна подія не надійде й дедуплікувати буде нічого. Створення ідентифікатора в обробнику кліку та його передавання зберігають пару саме в тому випадку, через який серверне вимірювання й з'явилося.
Мої події в Meta все одно не дедуплікуються. Що перевірити?
Чотири речі, у такому порядку: назва події однакова з обох боків, ідентифікатор події саме однаковий, а не просто присутній з обох боків, дві події відстоять одна від одної на секунди, і обидві оголошують джерело дії website. У Events Manager є вкладка Test Events, яка показує, яка половина надійшла.
Чи працює це на Cloudflare Workers або Vercel Edge?
Так. Серверна точка входу використовує лише fetch і WebCrypto, без вбудованих модулів Node, тому вона працює без змін на Node, Bun, Deno і в середовищах edge.
Чи надсилає бібліотека дані ще кудись, окрім рекламних платформ?
Ні. Немає ні телеметрії, ні власного сервісу. Єдині мережеві виклики, які вона робить, — ті, що ви налаштували, до вибраних вами платформ.
Спершу зроблено для власної воронки
LoomaScale керує Google Ads і Meta Ads із ChatGPT та Claude. Ця бібліотека — шар вимірювання під тим продуктом, і ми опублікували її, бо проблема дедуплікації, яку вона вирішує, трапляється в кожного рекламодавця.
Подивитися, що робить LoomaScale