{
"client_id": "123456789.987654321",
"non_personalized_ads": false,
"events": [
{
"name": "purchase",
"params": {
"transaction_id": "ORDER_12345",
"affiliation": "Online Store",
"value": 249.99,
"currency": "USD",
"tax": 19.99,
"shipping": 10.00,
"coupon": "SUMMER2025",
"items": [
{
"item_id": "SKU_001",
"item_name": "Solar Panel Kit",
"affiliation": "Online Store",
"coupon": "SUMMER2025",
"currency": "USD",
"discount": 20.00,
"index": 1,
"item_brand": "SunPower",
"item_category": "Energy",
"item_variant": "Large",
"price": 199.99,
"quantity": 1
},
{
"item_id": "SKU_002",
"item_name": "Battery Storage",
"price": 50.00,
"quantity": 1
}
]
}
}
]
}
Пользователь совершает действие на сайте
👉 Например, оформляет заказ и нажимает кнопку «Оплатить»
↓
Сервер обрабатывает заказ
👉 После успешной оплаты backend подтверждает заказ и получает данные: transaction_id, сумма, список товаров и т.д.
↓
Формируется событие в формате JSON
👉 Сервер собирает все параметры события (client_id, items, value, currency, и т.д.)
в нужной структуре под GA4
↓
Отправка события на endpoint GA4
👉 POST-запрос отправляется на:
https://www.google-analytics.com/mp/collect?measurement_id=G-XXXXXXXXXX&api_secret=YOUR_API_SECRET
↓
Событие попадает в GA4 через Measurement Protocol
👉 Оно отображается в DebugView и попадает в стандартные отчёты GA4
(как будто его отправил GTM или gtag.js)
↓
Событие можно использовать в Google Ads как конверсию
👉 Если настроен импорт конверсий из GA4 — событие автоматически попадёт в Google Ads
# 🛠️ Техническое задание: Передача события «Покупка» в Google Analytics 4 (через Measurement Protocol + UTM)
## 📌 Цель
Настроить серверную отправку события **purchase** в GA4 с помощью Measurement Protocol, включая полные eCommerce-параметры и UTM-метки.
---
## 📥 Что нужно от разработчика
### ✅ 1. Сбор и подготовка данных на сервере
При подтверждении покупки собрать следующие данные:
* `client_id` (из куки `_ga`, например `GA1.1.123456789.987654321` → `123456789.987654321`)
* `transaction_id`, `value`, `currency`, `tax`, `shipping`, `coupon`
* Массив товаров `items[]` с деталями по каждому товару:
* `item_id`, `item_name`, `item_brand`, `item_category`, `price`, `quantity`, `discount`, `coupon`, `variant`
* Значения UTM-меток (если они были в URL визита):
* `utm_source`, `utm_medium`, `utm_campaign`, `utm_term`, `utm_content`
### ✅ 2. Подготовка и отправка запроса
**Endpoint:**
```
POST https://www.google-analytics.com/mp/collect?measurement_id=G-XXXXXXXXXX&api_secret=XXXXXXXXXX
```
**Заголовки:**
```
Content-Type: application/json
```
**Пример тела запроса (JSON):**
```json
{
"client_id": "123456789.987654321",
"events": [
{
"name": "purchase",
"params": {
"transaction_id": "T_12345",
"value": 199.00,
"currency": "USD",
"tax": 19.99,
"shipping": 10.00,
"coupon": "SUMMER2025",
"event_id": "abc123-uuid", // 👈 Уникальный ID для дедупликации
"items": [
{
"item_id": "SKU_001",
"item_name": "Solar Panel Kit",
"affiliation": "Online Store",
"coupon": "SUMMER2025",
"currency": "USD",
"discount": 20.00,
"index": 1,
"item_brand": "SunPower",
"item_category": "Energy",
"item_variant": "Large",
"price": 199.99,
"quantity": 1
}
],
"source": "facebook",
"medium": "cpc",
"campaign": "spring_sale",
"term": "solar_panels",
"content": "ad_variant_1"
}
}
]
}
✅ Как работает дедупликация в GA4:
Google использует пару параметров для идентификации события:
event_name — название события (например, "purchase")
event_id — уникальный идентификатор события (одинаковый на клиенте и на сервере)
Если в течение короткого периода времени (обычно ~1 минута) приходит два события с одинаковыми event_name и event_id, Google учтёт только первое.
🔧 Что реализовать в проекте (в формате ТЗ):
📥 На клиенте (сайт, GTM, gtag):
При генерации события (например, "purchase") создать уникальный event_id.
Можно использовать crypto.randomUUID() или uuidv4() (если есть библиотека).
Передавать event_id в GA4 событии:
gtag('event', 'purchase', {
transaction_id: 'T12345',
value: 199.00,
currency: 'USD',
event_id: 'abc123-uuid'
});
📤 На сервере (Measurement Protocol):
Отправлять тот же event_id, что и на клиенте.
Пример JSON тела запроса:
{
"client_id": "123456789.987654321",
"events": [
{
"name": "purchase",
"params": {
"transaction_id": "T12345",
"value": 199.00,
"currency": "USD",
"event_id": "abc123-uuid"
}
}
]
}
📌 Примечание:
event_id должен быть одинаковым в клиентском и серверном вызове.
Лучше всего его генерировать на бекенде и "вкладывать" в dataLayer или HTML как hidden input, чтобы клиентская часть тоже могла его использовать.
💡 Зачем это всё?
Без event_id GA4 будет считать события с клиента и сервера отдельно, что приведёт к двойному учёту конверсий и искажению данных в отчетах и Google Ads.
## 🧭 Обработка UTM-меток
* UTM-метки нужно **сохранять при первом заходе пользователя на сайт** (через JS и localStorage/cookie).
* При оформлении заказа передавать значения этих меток на сервер.
* Включить их в `params` JSON, как показано выше.
### Важно:
UTM-метки в Measurement Protocol **не попадают в отчёты GA4 как source/medium**, если только:
1. Они не были захвачены ранее через клиентский `gtag`/GTM
2. Или не используются как **Custom Dimensions** (нужно создать в интерфейсе GA4)
---
❗ Важно:
В GA4 нельзя использовать utm_* как параметры в Measurement Protocol. Вместо этого нужно использовать:
source
medium
campaign
term
content
## 🔎 Проверка корректности:
* Протестировать JSON через [GA4 Event Builder](https://ga-dev-tools.google/ga4/event-builder/)
* Проверить событие в DebugView GA4
* Убедиться, что все параметры передаются, особенно `client_id`, `transaction_id`, `items[]`
* Настроить дедупликацию, если используется параллельный client-side трекинг
---
## 🎯 Дополнительно
* Возможна отправка `user_id` (если клиент авторизован)
* Можно добавить `timestamp_micros` для ретроспективной передачи событий
## ✅ Готово
После выполнения все события будут попадать в GA4 надёжно и независимо от браузерных ограничений. Готово к использованию в рекламных системах.
POST https://www.google-analytics.com/mp/collect?measurement_id=G-XXXXXXX&api_secret=XXXXXXXX
Content-Type: application/json
{
"client_id": "123456789.987654321",
"events": [
{
"name": "purchase",
"params": {
"transaction_id": "T_12345",
"value": 199.00,
"currency": "USD",
"tax": 19.99,
"shipping": 10.00,
"coupon": "SUMMER2025",
"items": [
{
"item_id": "SKU_001",
"item_name": "Solar Panel Kit",
"affiliation": "Online Store",
"coupon": "SUMMER2025",
"currency": "USD",
"discount": 20.00,
"index": 1,
"item_brand": "SunPower",
"item_category": "Energy",
"item_variant": "Large",
"price": 199.99,
"quantity": 1
}
],
"utm_source": "facebook",
"utm_medium": "cpc",
"utm_campaign": "spring_sale",
"utm_term": "solar_panels",
"utm_content": "ad_variant_1"
}
}
]
}
$ch = curl_init('https://www.google-analytics.com/mp/collect?measurement_id=...&api_secret=...');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_exec($ch);
curl_close($ch);
import requests
response = requests.post('https://www.google-analytics.com/mp/collect?...', json=payload)
import requests
response = requests.post('https://www.google-analytics.com/mp/collect?...', json=payload)
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://www.google-analytics.com/mp/collect?..."))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonPayload))
.build();
jsCopyEditfunction getClientIdFromGaCookie() {const gaCookie = document.cookie.split('; ').find(row => row.startsWith('_ga='));if (!gaCookie) return null;const gaValue = gaCookie.split('=')[1];const parts = gaValue.split('.');if (parts.length >= 4) {return `${parts[2]}.${parts[3]}`;}return null;}
jsCopyEditfunction() {return window.ga && ga.getAll? ga.getAll()[0].get('clientId'): null;}
jsCopyEditgtag('get', 'G-XXXXXXXXXX', 'client_id', function(clientID) {// передать на сервер});
pythonCopyEditimport uuiddef generate_client_id():return f"{uuid.uuid4().int >> 64}.{uuid.uuid4().int >> 64}"
htmlCopyEdit<input type="hidden" name="client_id" id="client_id"><script>document.getElementById("client_id").value = getClientIdFromGaCookie();</script>