Как передавать конверсии в Google Ads

Как передавать конверсии в Google Ads

Если льёте на наши офферы с Google Ads — можно настроить так, чтобы каждая подтверждённая конверсия автоматически прилетала в ваш рекламный кабинет и привязывалась к нужному клику. Google начинает видеть реальный результат по вашим кампаниям и лучше оптимизирует показы на Поиске и в Demand Gen.

Всё разворачивается у вас, под вашим собственным Google Ads и вашим собственным Cloudflare-аккаунтом — мы просто отдаём готовый скрипт и показываем, куда какие данные вписать. Бесплатно, займёт минут 15–20.

Зачем это нужно

Когда пользователь кликает по объявлению, Google подставляет в ссылку gclid (Google Click ID). Если конверсия — лид, депозит, продажа — подтверждается не на сайте через пиксель, а у нас в системе, обычный клиентский тег её не увидит. Конверсию нужно передать вручную, привязав к тому самому gclid, чтобы Google Ads видел реальный результат.

Для этого используется официальный Google Data Manager API — актуальный способ передачи конверсий у Google.

Что нужно сделать

1. Создайте конверсию в своём Google Ads

Инструменты → Конверсии → Создать → Импорт → Клики. Тип действия — «Website (Import from clicks)».

Откройте созданную конверсию — в адресной строке параметр ctId=.... Это ваш conversion_action_id, понадобится в скрипте.

2. Создайте сервис-аккаунт в Google Cloud

  • Заведите проект на console.cloud.google.com, включите в нём Data Manager API
  • Создайте service account (IAM & Admin → Service Accounts → Create), скачайте JSON-ключ
  • В своём Google Ads: Пользователи → Пригласить пользователя → впишите e-mail сервис-аккаунта (поле client_email из JSON-ключа) → права Standard

3. Разверните скрипт на Cloudflare

  • Заведите аккаунт на dash.cloudflare.com (бесплатно)
  • Поставьте wrangler: npm install -g wrangler, затем wrangler login
  • Скопируйте wrangler.toml и src/worker.js из раздела «Скрипт» ниже к себе в папку
  • wrangler kv:namespace create TOKENS — полученный ID впишите в wrangler.toml
  • Задайте секреты (команды ниже) и выполните wrangler deploy — получите свой адрес вида https://ваш-воркер.ваш-субдомен.workers.dev
 wrangler secret put SERVICE_ACCOUNT_JSON # весь JSON-ключ из шага 2 wrangler secret put GOOGLE_ADS_CUSTOMER_ID # ваш customer_id, без дефисов wrangler secret put CONVERSION_ACTION_ID # ваш ctId из шага 1 wrangler secret put POSTBACK_SECRET # придумайте любой случайный токен

4. Прокиньте gclid до нашей трекинг-ссылки

Важно понимать: {gclid} — это макрос именно Google Ads, и подставляется он только в тот URL, который вписан напрямую в поле «Конечный URL» в настройках вашей кампании. Дальше зависит от того, ведёт реклама сразу на нашу ссылку или через прокладку.

Если объявление ведёт сразу на нашу трекинг-ссылку — всё просто, в Конечном URL в Google Ads пишете:

 ссылканаблек.com?sub_id5={gclid}

Google сам подставит реальный gclid при клике, он долетит до нас без доп. действий.

Если между рекламой и нашей ссылкой стоит прокладка (клоака, промежуточный лендинг) — тогда в Google Ads вписан не наш линк, а адрес этой прокладки, и подстановка {gclid} происходит там, а не в нашей ссылке:

 Конечный URL в Google Ads: сайтсклоакой.com?gclid={gclid}

В этом случае саму прокладку нужно донастроить: она должна прочитать параметр gclid из входящего запроса (реальное значение, которое уже подставил Google) и прокинуть его дальше при редиректе на нашу ссылку:Клик по рекламеGoogle Ads подставляет gclidсайтсклоакой.com?gclid=Cj0KCQjw9L3…ссылканаблек.com?sub_id5=Cj0KCQjw9L3…Наша платформаКлик сохранён с этим id

Синие блоки — это один и тот же клик, только под разными именами параметра: клоака получает значение от Google как gclid, а дальше сама подставляет его в ссылку на блек уже как sub_id5.

Если вписать {gclid} не в Google Ads, а прямо в настройки прокладки как её собственный редирект-URL — до нас долетит буквальный текст {gclid} (семь символов), а не настоящий click id: подстановку делает только Google Ads, и только для того URL, который видит сам.

Если sub_id5 занят под что-то своё — берите любой свободный слот из sub_id1-5 или aff_param1-5.

5. Пропишите постбек в личном кабинете нашей платформы

В настройках постбека на цель Approved укажите адрес своего воркера из шага 3:

 https://ваш-воркер.ваш-субдомен.workers.dev/postback ?secret=ВАШ_POSTBACK_SECRET &gclid={sub_id5} &txid={transaction_id} &value={amount} &currency={offer_currency} &status={conv_status}

(замените {sub_id5} на тот слот, который использовали в шаге 4)

Так это будет выглядеть с уже подставленными реальными значениями, когда сработает постбек на конкретную конверсию (у вас, конечно, будут свои воркер, секрет и gclid — здесь просто наглядный пример):

 https://gads-conversion-relay.egor-worker.workers.dev/postback?secret=x7K9pL2mQwZ4vN8t&gclid=Cj0KCQjw9L3BhDwARIsAM7MKi3vN2xY7pQrT4wJ8mK1lS6fH3dG9cV-abc123&txid=TX-8842910&value=45.00&currency=USD&status=approved

Важно: в Google должны улетать только реальные подтверждённые (Approved) конверсии, привязанные к настоящим кликам. Отправка неподтверждённых или сфабрикованных событий как реальных конверсий — нарушение политик Google Ads и риск для вашего аккаунта.

Готово. Дальше ничего делать не нужно — при подтверждённой конверсии по вашему трафику скрипт сам отправит её в ваш Google Ads с привязкой к клику.

Скрипт

wrangler.toml

 name = "gads-conversion-relay" main = "src/worker.js" compatibility_date = "2025-01-01" kv_namespaces = [ { binding = "TOKENS", id = "ВАШ_KV_NAMESPACE_ID" } ]

src/worker.js

 export default { async fetch(request, env) { const url = new URL(request.url); if (url.pathname !== '/postback') { return new Response('Not found', { status: 404 }); } const p = url.searchParams; if (p.get('secret') !== env.POSTBACK_SECRET) { return new Response('Forbidden', { status: 403 }); } // шлём в Google только подтверждённые конверсии const status = (p.get('status') || '').toLowerCase(); if (status && status !== 'approved') { return new Response('Skipped (not approved)', { status: 200 }); } const gclid = p.get('gclid'); const transactionId = p.get('txid'); const value = parseFloat(p.get('value') || '0'); const currency = (p.get('currency') || 'USD').toUpperCase(); if (!gclid || !transactionId) { return new Response('Missing gclid or txid', { status: 400 }); } try { const accessToken = await getAccessToken(env); const result = await sendConversion(env, accessToken, { gclid, transactionId, value, currency, }); return new Response(JSON.stringify(result), { status: 200, headers: { 'content-type': 'application/json' }, }); } catch (err) { console.error(err); return new Response(`Error: ${err.message}`, { status: 500 }); } }, }; /* ---------- OAuth2: JWT-bearer flow для service account ---------- */ async function getAccessToken(env) { const cached = await env.TOKENS.get('access_token', { type: 'json' }); if (cached && cached.expiresAt > Date.now() + 30_000) { return cached.token; } const sa = JSON.parse(env.SERVICE_ACCOUNT_JSON); const now = Math.floor(Date.now() / 1000); const header = { alg: 'RS256', typ: 'JWT' }; const claims = { iss: sa.client_email, scope: 'https://www.googleapis.com/auth/datamanager', aud: 'https://oauth2.googleapis.com/token', iat: now, exp: now + 3600, }; const unsigned = `${base64url(JSON.stringify(header))}.${base64url(JSON.stringify(claims))}`; const signature = await signRS256(unsigned, sa.private_key); const assertion = `${unsigned}.${signature}`; const resp = await fetch('https://oauth2.googleapis.com/token', { method: 'POST', headers: { 'content-type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', assertion, }), }); const data = await resp.json(); if (!resp.ok) { throw new Error(`Token exchange failed: ${JSON.stringify(data)}`); } await env.TOKENS.put( 'access_token', JSON.stringify({ token: data.access_token, expiresAt: Date.now() + data.expires_in * 1000 }), { expirationTtl: data.expires_in } ); return data.access_token; } function base64url(input) { const bytes = new TextEncoder().encode(input); let bin = ''; bytes.forEach((b) => (bin += String.fromCharCode(b))); return btoa(bin).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); } async function signRS256(data, pem) { const key = await importPrivateKey(pem); const sig = await crypto.subtle.sign( 'RSASSA-PKCS1-v1_5', key, new TextEncoder().encode(data) ); let bin = ''; new Uint8Array(sig).forEach((b) => (bin += String.fromCharCode(b))); return btoa(bin).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); } async function importPrivateKey(pem) { const contents = pem .replace('-----BEGIN PRIVATE KEY-----', '') .replace('-----END PRIVATE KEY-----', '') .replace(/\s/g, ''); const raw = Uint8Array.from(atob(contents), (c) => c.charCodeAt(0)); return crypto.subtle.importKey( 'pkcs8', raw.buffer, { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' }, false, ['sign'] ); } /* ---------- Отправка события в Data Manager API ---------- */ async function sendConversion(env, accessToken, { gclid, transactionId, value, currency }) { const body = { destinations: [ { operatingAccount: { accountType: 'GOOGLE_ADS', accountId: env.GOOGLE_ADS_CUSTOMER_ID, }, productDestinationId: env.CONVERSION_ACTION_ID, }, ], events: [ { eventTimestamp: new Date().toISOString(), transactionId, adIdentifiers: { gclid }, currency, conversionValue: value, eventSource: 'WEB', }, ], validateOnly: false, // на этапе теста поставьте true }; const resp = await fetch('https://datamanager.googleapis.com/v1/events:ingest', { method: 'POST', headers: { Authorization: `Bearer ${accessToken}`, 'content-type': 'application/json', }, body: JSON.stringify(body), }); const data = await resp.json(); if (!resp.ok) { throw new Error(`Data Manager API error: ${JSON.stringify(data)}`); } return data; }

Частые вопросы

Долго ждать, пока конверсии появятся в оптимизации ставок?
У новой конверсии в Google Ads есть 14-дневный технический период — она сразу видна в отчётах, но участвует в назначении ставок только по его истечении. Это особенность самого Google Ads.

Почему постбек только на Approved?
Отправка неподтверждённых или отклонённых конверсий как реальных — нарушение политик Google Ads и риск для вашего аккаунта. Скрипт и сам отфильтрует по статусу, но лучше сразу настроить постбек только на Approved.

Нужно ли что-то платить?
Нет. Data Manager API бесплатный, Cloudflare Workers на бесплатном тарифе покрывает 100 000 запросов в день.

Как проверить перед боем?
Пока в скрипте не выставлено validateOnly: false, Google валидирует запрос, но не засчитывает конверсию. Проверьте вручную (дёрните /postback с тестовыми параметрами, убедитесь в ответе 200 OK), и только потом переключайте на false.

Вывод

Автоимпорт конверсий — бесплатная и разовая настройка, которая даёт Google Ads реальный сигнал о результатах ваших кампаний вместо простого счётчика кликов. Как только связка настроена — она работает сама, без дальнейшего вмешательства.

Оставить комментарий

1WIN PARTNERS
1win Partners: до 50% дохода!
Начать зарабатывать
1win Partners — партнерская программа с высокими ставками (до 50% с дохода). Привлекайте клиентов через сайт, соцсети или CPA-сети. Готовая реклама, аналитика, моментальные выплаты. Поддержка 24/7. Зарабатывайте уже сейчас!

AFFILIATE.TOP
Affiliate Top – топовая партнерка, прямой рекламодатель лидеров трейдинг индистрии.
Начать зарабатывать
Самый высокий процент профита на рынке, 165+ гео, еженедельные выплаты, офферы с высоким конвертом, саппорт 24/7, поддержка партнеров: API, постбеки, сигналы. Присоединяйся и будь в топе!!!

M1.TOP
Партнерская сеть M1 появилась одной из первых в 2013 году и работает в вертикалях нутра и товарка.
Начать зарабатывать
Партнерская сеть M1 появилась одной из первых в 2013 году и работает в вертикалях нутра и товарка. Cегодня партнерка предоставляет больше 1000 авторских офферов в 11 странах Европы и Латинской Америки. M1 является прямым рекламодателем по нутре в ЕС и Латаме.

CLOAKING.HOUSE
Cloaking.House - сервис для фильтрации трафика.
Начать пользоваться
Cloaking.House - сервис для фильтрации трафика и защиты от банов на Facebook, Google, TikTok и тд. Использует ИИ, гибкие фильтры, настройка за 2 минуты, не требует навыков программирования. от $49/мес, 7-дневный пробный период.

Alanbase
SaaS-платформа для создания партнерской программы и трекер для аффилейт-трафика.
Начать пользоваться
Saas-платформа, для создании партнерской сети, Alanbase легко собирается под нужды абсолютно любой вертикали. При этом у нас есть готовые инстансы под gambling, e-commerce и медиабаинг-команд. Скидка 20% по промокоду AFF24.

Dolphin{anty} - Антидетект браузер
Dolphin{anty} - Антидетект браузер нового поколения
Начать пользоваться
Антидетект браузер, который дает рынку лучшее из возможного. Надежная подмена фингерпринтов для крепких аккаунтов. Автоматизация, фарминг куки, работа в команде и другое. Скидка 20% по промокоду AFF24

ROLLERADS.COM
Перейти на сайт
RollerAds — рекламная сеть, которая специализируется на push, pop up и in-page push трафике. Только за прошлый год через них было совершено 11+ млн конверсий, а количество показов перевалило за 620 млрд. CPM, CPC, Smart модели. Минимальный депозит для оплаты или вывода — $50.

ADPROFEX.COM
Перейти на сайт
AdProfex - конвертящий источник Native и Push трафика без ботов.
Вертикали, на которых зарабатывают с AdProfex: Nutra, mVAS, Finance, Сontent Websites, News, Search Monetization, Sweepstakes, Betting, Utilities, Gambling, Dating. Гео: Европа, Латинская Америка, Азия и СНГ

MOBIADS.PRO
MobiAds.pro — это рекламная сеть, специализирующаяся на мобильной рекламе.
Перейти на сайт
MobiAds.pro — это рекламная сеть, специализирующаяся на мобильной рекламе. Платформа предлагает инструменты для монетизации мобильных приложений и сайтов, а также для продвижения мобильных продуктов.

Что будем искать? Например,Как настроить Postback?

Мы в социальных сетях