Skip to main content
Configure event sources on a seller account for conversion tracking. Supports upsert semantics, seller-managed sources, and setup instructions. Response Time: ~1s (synchronous configuration) Request Schema: /schemas/v2/media-buy/sync-event-sources-request.json Response Schema: /schemas/v2/media-buy/sync-event-sources-response.json

Quick Start

Configure an event source for purchase tracking:
import { testAgent } from "@adcp/client/testing";
import { SyncEventSourcesResponseSchema } from "@adcp/client";

const result = await testAgent.syncEventSources({
  account_id: "acct_12345",
  event_sources: [
    {
      event_source_id: "website_pixel",
      name: "Main Website Pixel",
      event_types: ["purchase", "lead", "add_to_cart"],
      allowed_domains: ["www.example.com", "shop.example.com"],
    },
  ],
});

if (!result.success) {
  throw new Error(`Request failed: ${result.error}`);
}

// Validate response against schema
const validated = SyncEventSourcesResponseSchema.parse(result.data);

// Check for operation-level errors first (discriminated union)
if ("errors" in validated && validated.errors) {
  throw new Error(`Operation failed: ${JSON.stringify(validated.errors)}`);
}

if ("event_sources" in validated) {
  for (const source of validated.event_sources) {
    console.log(`${source.event_source_id}: ${source.action}`);
    if (source.setup?.snippet) {
      console.log(`  Install: ${source.setup.snippet_type}`);
    }
  }
}

Request Parameters

ParameterTypeRequiredDescription
account_idstringYesAccount to configure event sources for
event_sourcesEventSource[]NoEvent sources to sync. When omitted, the call is discovery-only and returns all existing event sources without modification.
delete_missingbooleanNoWhen true, buyer-managed event sources on the account not in this request are removed (default: false)

Event Source Object

FieldTypeRequiredDescription
event_source_idstringYesUnique identifier for this event source
namestringNoHuman-readable name
event_typesEventType[]NoEvent types this source handles. If omitted, accepts all event types.
allowed_domainsstring[]NoDomains authorized to send events for this source

Response

Success Response:
  • event_sources - Results for each event source, including both synced and seller-managed sources on the account
Error Response:
  • errors - Array of operation-level errors (auth failure, account not found)
Note: Responses use discriminated unions - you get either success fields OR errors, never both. Each event source in success response includes:
  • All request fields
  • seller_id - Seller-assigned identifier for this event source
  • action - What happened: created, updated, unchanged, deleted, failed
  • action_source - Type of event source (website pixel, app SDK, etc.)
  • managed_by - Who manages this source: buyer or seller
  • setup - Implementation details (snippet, instructions)
  • errors - Per-source errors (only when action: "failed")
See schema for complete field list: sync-event-sources-response.json

Common Scenarios

Discovery Only

Discover all event sources on an account (including seller-managed sources) without making changes. Useful for platform-managed conversion tracking where the seller provides always-on attribution:
import { testAgent } from "@adcp/client/testing";
import { SyncEventSourcesResponseSchema } from "@adcp/client";

const result = await testAgent.syncEventSources({
  account_id: "acct_12345",
});

if (!result.success) {
  throw new Error(`Request failed: ${result.error}`);
}

const validated = SyncEventSourcesResponseSchema.parse(result.data);

if ("errors" in validated && validated.errors) {
  throw new Error(`Operation failed: ${JSON.stringify(validated.errors)}`);
}

if ("event_sources" in validated) {
  for (const source of validated.event_sources) {
    console.log(`${source.event_source_id} (${source.managed_by}): ${source.name}`);
  }
}

Multiple Event Sources

Configure separate sources for website and app:
import { testAgent } from "@adcp/client/testing";
import { SyncEventSourcesResponseSchema } from "@adcp/client";

const result = await testAgent.syncEventSources({
  account_id: "acct_12345",
  event_sources: [
    {
      event_source_id: "web_pixel",
      name: "Website Pixel",
      event_types: ["purchase", "lead", "add_to_cart", "view_content"],
      allowed_domains: ["www.example.com"],
    },
    {
      event_source_id: "app_sdk",
      name: "Mobile App SDK",
      event_types: ["purchase", "app_install", "app_launch"],
    },
  ],
});

if (!result.success) {
  throw new Error(`Request failed: ${result.error}`);
}

const validated = SyncEventSourcesResponseSchema.parse(result.data);

if ("errors" in validated && validated.errors) {
  throw new Error(`Operation failed: ${JSON.stringify(validated.errors)}`);
}

if ("event_sources" in validated) {
  for (const source of validated.event_sources) {
    console.log(`${source.event_source_id} (${source.managed_by}): ${source.action}`);
  }
}

Discovering Seller-Managed Sources

Sellers may provide always-on event sources (e.g. Amazon sales attribution). These appear in the response with managed_by: "seller" alongside your buyer-managed sources:
test=false
{
  "event_sources": [
    {
      "event_source_id": "web_pixel",
      "name": "Website Pixel",
      "seller_id": "px_abc123",
      "action": "created",
      "managed_by": "buyer",
      "setup": {
        "snippet": "<script src=\"https://seller.example/pixel/px_abc123.js\"></script>",
        "snippet_type": "javascript",
        "instructions": "Place this tag in the <head> of all pages where you want to track events."
      }
    },
    {
      "event_source_id": "seller_sales_attribution",
      "name": "Sales Attribution",
      "seller_id": "internal_attr",
      "action": "unchanged",
      "managed_by": "seller",
      "action_source": "in_store"
    }
  ]
}
Products with conversion_tracking.platform_managed: true indicate the seller provides these sources.

Clean Sync with delete_missing

Replace all buyer-managed event sources on the account:
import { testAgent } from "@adcp/client/testing";
import { SyncEventSourcesResponseSchema } from "@adcp/client";

const result = await testAgent.syncEventSources({
  account_id: "acct_12345",
  delete_missing: true,
  event_sources: [
    {
      event_source_id: "unified_pixel",
      name: "Unified Tracking Pixel",
    },
  ],
});

if (!result.success) {
  throw new Error(`Request failed: ${result.error}`);
}

const validated = SyncEventSourcesResponseSchema.parse(result.data);

if ("errors" in validated && validated.errors) {
  throw new Error(`Operation failed: ${JSON.stringify(validated.errors)}`);
}

if ("event_sources" in validated) {
  for (const source of validated.event_sources) {
    if (source.action === "deleted") {
      console.log(`Removed: ${source.event_source_id}`);
    } else {
      console.log(`Active: ${source.event_source_id} (${source.action})`);
    }
  }
}

Setup Instructions

The response includes setup details for each event source. The setup object tells you how to activate the source:
snippet_typeDescriptionAction Required
javascriptJavaScript tag for website pagesPlace in <head> of tracked pages
htmlHTML pixel/iframePlace before </body>
pixel_urlURL that fires on eventsSend GET request on each event
server_onlyNo client-side tag neededUse log_event API directly

Error Handling

Error CodeDescriptionResolution
ACCOUNT_NOT_FOUNDAccount does not existVerify account_id from account setup
INVALID_EVENT_TYPEUnrecognized event typeCheck seller’s supported_event_types in get_adcp_capabilities
DUPLICATE_EVENT_SOURCE_IDMultiple sources with same ID in requestUse unique event_source_id values
RATE_LIMIT_EXCEEDEDToo many sync requestsWait and retry with exponential backoff

Best Practices

  1. Sync before logging - Always configure event sources before sending events via log_event. Events sent to unconfigured sources will be rejected.
  2. Use descriptive IDs - Choose event_source_id values that are meaningful (e.g. web_pixel, app_sdk, crm_import) rather than opaque identifiers.
  3. Specify event_types - Restrict each source to relevant event types for better validation and debugging.
  4. Check seller capabilities - Use get_adcp_capabilities to discover supported event types, UID types, and action sources before configuring event sources.
  5. Install setup snippets - When the response includes setup instructions, install the provided snippet before logging events. Server-only sources (snippet_type: "server_only") skip this step.
  6. Handle seller-managed sources - The response may include sources with managed_by: "seller" that you didn’t configure. These are always-on and provide additional attribution data.

Next Steps