Skip to main content

Audience activation pipelines

A saved segment answers “who are we talking about.” An activation answers “where does that audience keep landing.” An activation is a registered connection that publishes a segment (or list) to an external target — a paid-media network (Google Ads, Meta, TikTok, LinkedIn, Snapchat, Pinterest, Reddit, The Trade Desk, Criteo) or your own HTTPS webhook sink — on a schedule you control. Orbit handles the hashing, batching, and signature; you wire the destination, approve the run if your policy requires it, and watch the history. For one-off pulls, the ad-hoc CSV export is the right tool. For a recurring publish, an activation is.

1. What an activation contains

One destination is one row of config:
  • The source segment id the run resolves membership from.
  • The target — an ad platform’s audience id (Custom Audience, user list, DMP segment) reached over a Nango OAuth connection, or your webhook URL, signed per delivery.
  • Identifiers per member mapped to destination fields. Ad networks take hashed email/phone/name/address/mobile-id columns; a webhook receives the identifiers you forward. Either way, every member needs at least one strong identifier (email, work email, phone, or mobile advertising id) — rows with only a name are rejected, not silently dropped.
  • A refresh cadence (schedule_minutes) — null means manual runs only.
  • Run history and status per activation, per destination (ok, partial, failed, skipped).
Every run is audited, and ad-network pushes hash PII with SHA-256 before it leaves Orbit.

2. Prerequisites

Before the first run:
  • A saved segment (POST /api/v1/contacts/segments) — set auto_refresh so membership the activation re-reads is current.
  • Target credentials: an OAuth connection to the ad network (registered in Orbit as a Nango connection id), or an HTTPS webhook URL you control.
  • Roles: owner, admin, or developer on the API key for every config and activate call.
  • Consent and suppression hygiene: members flagged consent: false/suppressed: true fail the pre-activation gate below its thresholds — keep those flags honest at ingest.

3. Create the activation config

Wire the destination once; only supplied keys change on each PATCH.
For a webhook sink instead of an ad network:
The secret is encrypted at rest and never returned by GET; deliveries are signed X-Orbit-Signature: t=<unix-sec>,v1=<hmac-sha256>, the same scheme your existing Orbit webhook verifier already uses. Pass empty string to clear it.

4. Run an activation

Push the current membership explicitly, or refresh a suppression (remove) run:
Members resolve to this profile shape: email, email_work, phone, first_name, last_name, city, state, zip, country, madid. A request carries up to 10,000 members; a segmentation job sends batchfuls in one run. Dry-run first with POST /api/v1/cdp/audience/preflight/:platform — same verdict, nothing dispatched. If a gate blocks and the threshold is genuinely fine for your destination, send override_preflight: true (audited) — unless this org has maker-checker on, in which case the run queues for approval: submit without an approval_id to enqueue, an owner/admin approves via POST /api/v1/cdp/audience/approvals/:id/decision, then re-submit with the returned approval_id. Webhook variant:
Your sink receives one signed POST of event type cdp.segment.activation with segment_id, operation, member_count, and the members array.

5. Read status and failures

Each destination reports last_activation_status; every run lands in a capped history (newest first, 50 entries).
The run detail shows requested / matched / skipped member counts, batches dispatched, an error message when a dispatch call failed, and per-member rejections (index + reason, never PII). Retry a non-ok run with POST /api/v1/cdp/audience/activations/:id/retry and a corrected member batch — it is recorded as a new run linked to the original. Status meanings:
  • ok — every batch the network accepted.
  • partial — some batches failed; the member-level detail names why.
  • failed — nothing accepted (quota breach, revoked token).
  • skipped — nothing matchable, or no connection wired at dispatch time.

6. Cadence and delta updates

Setting schedule_minutes enrolls the destination in a scheduled sweep (a background worker that ticks every 15 minutes and runs a destination when its cadence has elapsed). Set segment auto_refresh so a scheduled run always re-resolves fresh membership — spin correspondingly. The delta weapon is operation:
  • add — newest members; acquisition or seeding a lookalike.
  • remove — suppression; drop existing customers from prospecting spend.
Lean on successive add/remove deltas rather than full re-uploads: the destination stays diff-shaped, and suppression runs are the cleanest way to stop spend on won-back customers.

7. Patterns

  • Churn-tier → ads. A churn-risk segment refreshes daily into a Google customer-match list; auto-suppress your own customers from prospecting.
  • VIP → email or ads. A high-LTV segment synced on a slow cadence (weekly) — refresh noise is worth less than accuracy here.
  • Win-back → webhook sink. Fan a lapsed-customer segment into your in-house orchestration endpoint; stack it on top of segment-triggered journeys so onboard entry and offboard suppression stay on one membership definition.
  • Incrementality. Set holdout_pct on the destination so the report can separate exposed conversions from a randomized control arm.

8. Troubleshooting

  • 409 CONNECTION_NOT_CONFIGURED / PLATFORM_NOT_ENABLED / AUDIENCE_NOT_CONFIGURED. The destination is not fully wired — enable it with an audience_id and (for ad networks) a nango_connection_id. Direct API PATCHes get the same precondition the dashboard enforces.
  • 422 AUDIENCE_PREFLIGHT_BLOCKED. Gate rejected the batch — too small, low identifier coverage, or consent/suppression violations. The failing check ids come back in the response; re-check POST .../preflight/:platform, then adjust the segment, the thresholds, or override deliberately.
  • 400 naming a field. Off-schema input — the message is field-prefixed (e.g. holdout_pct: ...), so read which key was refused.
  • Run status skipped with dispatch_skipped equal to your batches. No connection was resolved at dispatch — a cleared or never-wired nango_connection_id. Re-wire and retry the run.
  • Run status failed, error mentions quota / auth. The ad-network call was rejected (quota breach or a stale OAuth token). Refresh the connection token, wait out the quota window, then POST .../retry; only ok runs are refused as already-dispatched.
  • Zero matched members. The batch arrived with no strong identifier per row (name+address only). Resolve before activate — either the segment filter picks up empty profiles, or the field mapping at ingest is broken. A blank export downstream typically means exactly this.
  • Approval queue hangs. Maker-checker is on (GET .../approvals/settings shows require_activation_approval: true): request → approve → re-submit with the approval id. A supervisor cannot self-approve — a second person must sign.
Tenant-owned controls like consent checks and suppression lists gate every activation, and cleartext never reaches an ad network — digests only, counts only in the log.

See also