Skip to content
adscapi

AdCP interop

Map adscapi results onto the Ad Context Protocol (metric_id, qualifier) taxonomy and emit a schema-accurate provide_performance_feedback request.

Why

AdCP is an MCP-based standard for agentic advertising. Buy-side agents speak its measurement vocabulary. adscapi covers the measurement side — not media-buy. You still fire conversions with track; these helpers translate what came back.

Schema pin: dist/schemas/3.1.13 (provide-performance-feedback-request.json). Taxonomy: AdCP measurement taxonomy.

Measurements

toAdcpMeasurements emits one (metric_id, value) tuple per present finite number. Absent fields are omitted. 0 is present.

ts
import { toAdcpMeasurements } from 'adscapi';

const rows = await getReport('meta', secrets, { since: '2026-04-01', until: '2026-04-08' });
const totals = rows.reduce(
  (acc, r) => ({
    conversions: (acc.conversions ?? 0) + (r.conversions ?? 0),
    conversionValue: (acc.conversionValue ?? 0) + (r.conversionValue ?? 0),
    spend: (acc.spend ?? 0) + r.spend,
    impressions: (acc.impressions ?? 0) + r.impressions,
    roas: r.roas,
  }),
  {} as { conversions?: number; conversionValue?: number; spend?: number; impressions?: number; roas?: number },
);

const measurements = toAdcpMeasurements(totals);
// [{ metric_id: 'conversions', value }, { metric_id: 'spend', value }, …]

Accepted input keys: conversions, conversionValue (→ conversion_value), spend, impressions, clicks, roas, cpa.

One destination result

conversionToAdcpEvent represents a single track result as a conversion measurement. value is always 1. occurred is true only on a real successful send — dryRun and errors are occurred: false.

ts
import { conversionToAdcpEvent } from 'adscapi';

const results = await ads.conversions.track(event);
const mapped = results.map((r) => conversionToAdcpEvent(r, event));

event_id is copied from event.eventId when present, otherwise omitted.

Performance feedback

toPerformanceFeedback shapes the AdCP provide_performance_feedback request body. Required: idempotencyKey, mediaBuyId, measurementPeriod, performanceIndex. Defaults adcp_version to 3.1 and feedback_source to buyer_attribution.

ts
import { toPerformanceFeedback } from 'adscapi';

const body = toPerformanceFeedback({
  mediaBuyId: 'mb-9',
  idempotencyKey: 'adscapi-feedback-01',
  measurementPeriod: { start: '2026-04-01T00:00:00Z', end: '2026-04-08T00:00:00Z' },
  performanceIndex: 1.2,
});

Optional: packageId, creativeId, metricType, feedbackSource, adcpVersion, adcpMajorVersion, context, ext. This emits the request body. You POST it on the AdCP transport yourself.

Notes

  • Measurement interop only. adscapi does not place or mutate media buys.
  • toAdcpMeasurements / conversionToAdcpEvent do not invent extra wire fields.
  • metric_type on the feedback request is the legacy enum from schema 3.1.13 (overall_performance, conversion_rate, …) and is marked deprecated in-schema.

Related

  • Reporting getReport is the usual input to toAdcpMeasurements
  • conversions.track() — map each destination result with conversionToAdcpEvent