Overview
POST /api/buyer/advertisers/:advertiserId/log-event is a single-call ingest endpoint for sending conversion or marketing events to an advertiser. It accepts the standard ADCP event types — purchase, lead, add_to_cart, initiate_checkout, view_content, complete_registration, page_view, app_install, deposit, subscription — and a custom event type for events that don’t map to any of those.
Use it for:
- Bespoke conversion definitions — a “qualified demo booked” or “tier upgrade” event that doesn’t fit the standard taxonomy. Send
event_type: customwithcustom_event_name. - Internal-only events for ML training — engagement signals you want to feed measurement, even if they aren’t reportable conversions.
- Custom funnel steps — domain-specific milestones (game level reached, KYC step completed) that drive your bidding logic.
- Server-to-server batch ingestion — up to 10,000 events per call.
How it differs from event sources and measurement data
The three measurement ingest paths overlap; pick the one that matches the shape of your data.| Surface | What you send | Granularity | Best for |
|---|---|---|---|
Event sources (/event-sources/sync) | The configuration of where events come from (pixels, SDKs, MMPs) | Source registration | Onboarding a new pixel or feed once, then sending events through it |
Log events (/log-event) | Per-user, per-event records keyed to a registered event_source_id | One record per event (1–10,000 per call) | Bespoke conversion taxonomies, custom funnel steps, server-to-server event ingestion |
Measurement data (/measurement-data/sync) | Pre-aggregated outcomes for a time window and entity | One record per metric × window × campaign | MMP, CRM, or warehouse exports of weekly/daily aggregates |
log-event is the path for identified, per-user events at advertiser scope. Event sources are the configuration layer you call once; log-event is the runtime path you call repeatedly.
Every event must reference an
event_source_id that is already registered
on the advertiser via POST /advertisers/:advertiserId/event-sources/sync.
Events sent against an unregistered source are rejected. See the
Measurement & Incrementality guide
for event-source setup.Request shape
All examples use:Response
Top-level fields
| Field | Type | Required | Notes |
|---|---|---|---|
event_source_id | string | yes | Must match an event_source_id registered on the advertiser |
events | array | yes | 1–10,000 events per call |
test_event_code | string | no | Marks the request as test traffic — events are validated but excluded from production data |
Per-event fields
| Field | Type | Required | Notes |
|---|---|---|---|
event_id | string | yes | Unique within event_type + event_source_id. Resends with the same event_id are deduplicated. |
event_type | enum | yes | purchase, lead, add_to_cart, initiate_checkout, view_content, complete_registration, page_view, app_install, deposit, subscription, or custom |
event_time | ISO 8601 | yes | Must include offset (e.g. 2026-04-26T14:30:00-05:00) |
custom_event_name | string | conditional | Required when event_type: custom |
action_source | enum | no | website, app, in_store, phone_call, system_generated, other |
event_source_url | URL | conditional | Required when action_source: website |
user_match | object | no | Identity fields for attribution (see below) |
custom_data | object | no | Value, currency, order ID, items |
user_match — identity fields
Send at least one identifier per event. More identifiers = higher match rate.
| Field | Format | Notes |
|---|---|---|
uids | array of { type, value } | Universal IDs: rampid, id5, uid2, euid, pairid, maid |
hashed_email | 64-char lowercase hex | SHA-256 of lowercased, trimmed email |
hashed_phone | 64-char lowercase hex | SHA-256 of E.164-formatted phone |
click_id + click_id_type | string | Platform click identifier (fbclid, gclid, ttclid) |
client_ip | string | IP for probabilistic matching |
client_user_agent | string | UA for probabilistic matching |
custom_data — event payload
| Field | Type | Notes |
|---|---|---|
value | number | Monetary value of the event |
currency | string | ISO 4217 (USD, EUR, GBP) — required when value is set |
order_id | string | Unique transaction ID |
content_ids | array of strings | SKU / product IDs |
content_type | string | Category (product, service) |
num_items | integer | Item count |
contents | array of { id, quantity, price, brand } | Per-item detail |
Response shape
| Field | Type | Notes |
|---|---|---|
events_received | integer | Count of events in the request |
events_processed | integer | Count successfully queued |
partial_failures | array | Per-event failures with event_id, code, message |
warnings | array of strings | Non-fatal issues — low match quality, missing optional fields |
match_quality | number (0–1) | Aggregate match-quality score for the batch |
200 with partial_failures is normal — bad events are rejected individually, the rest succeed. Treat any failure as something to fix at source, not a transient error.
Best practices
Pick stable, descriptive custom_event_name values
Pick stable, descriptive custom_event_name values
Custom event names become the join key for downstream measurement and
reporting. Pick names you won’t want to change (
qualified_demo_booked,
kyc_step_2_complete). Renaming after launch breaks historical
continuity.Use a standard event_type when one fits
Use a standard event_type when one fits
If your event is genuinely a purchase or a lead, use
purchase or
lead. Standard types get first-class treatment in measurement and
optimization; custom events fall back to generic handling.Use event_id for idempotency
Use event_id for idempotency
event_id is the dedup key, scoped to event_type + event_source_id.
Re-sending the same event_id is safe — duplicates are dropped. Use
your stable upstream identifier (transaction ID, demo booking ID) so
retries don’t double-count.Send events in real time when you can
Send events in real time when you can
Recent events match better — click IDs and probabilistic signals decay
quickly. Aim for sub-hour latency for behavioral events; daily batches
are fine for offline conversions like CRM exports.
Use test_event_code in non-prod
Use test_event_code in non-prod
Set
test_event_code for staging traffic. Events validate end-to-end
but are excluded from production reporting and the measurement engine.Batch up to 10,000 events
Batch up to 10,000 events
The endpoint accepts up to 10,000 events per call. Batch larger flows
rather than firing one HTTP request per event — same data, much less
overhead.
Privacy
The same privacy contract applies whether an event ispurchase or custom. Custom events are not a back door for raw PII.
Related
Conversion API
Detailed identity-hashing rules and the same
log-event payload viewed
as a conversion-tracking integration.Measurement & Incrementality
Register event sources, configure measurement, and run incrementality
tests against the events you log.