Skip to Content
Elido is in closed beta — APIs are stable but rate-limits and quotas may change before GA. Request access →
GuidesCampaigns & A/B

Campaigns & A/B

A campaign is a named bag of links that shares a UTM template, an optional date window, and a single line in your analytics. A/B is configured per-link via variants[] and is independent of the campaign system — you can use either, both, or neither.

Create a campaign

curl -X POST \ https://api.elido.app/v1/workspaces/1/campaigns \ -H "Authorization: Bearer $ELIDO_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Spring 2026 launch", "description": "Coordinated push across email and paid", "utm_source": "spring2026", "utm_medium": "email", "utm_campaign": "launch", "start_date": "2026-05-01", "end_date": "2026-05-31" }'

Names are unique per workspace. The full UTM set (utm_source, utm_medium, utm_campaign, utm_term, utm_content) is optional and acts as a template — links assigned to the campaign inherit any UTM params they don’t override themselves.

curl -X POST \ https://api.elido.app/v1/workspaces/1/campaigns/7/links \ -H "Authorization: Bearer $ELIDO_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "link_ids": [42, 43, 44] }'

Up to 100 link IDs per call. A link belongs to at most one campaign; re-assigning moves it. Setting campaign_id on a link via PATCH /links/{id} works too if you’d rather keep campaign assignment in the link payload.

Remove with the same shape against DELETE:

curl -X DELETE \ https://api.elido.app/v1/workspaces/1/campaigns/7/links \ -H "Authorization: Bearer $ELIDO_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "link_ids": [42] }'

Deleting a campaign nulls campaign_id on its links — they survive.

Endpoints

MethodPath
GET/v1/workspaces/{ws}/campaigns
POST/v1/workspaces/{ws}/campaigns
PATCH/v1/workspaces/{ws}/campaigns/{id}
DELETE/v1/workspaces/{ws}/campaigns/{id}
GET/v1/workspaces/{ws}/campaigns/{id}/links
POST/v1/workspaces/{ws}/campaigns/{id}/links (assign)
DELETE/v1/workspaces/{ws}/campaigns/{id}/links (unassign)

A/B testing with variants

A link can have any number of variants[]. Each variant has a destination, a weight, and an optional label. The edge picks one per request:

{ "destination_url": "https://example.com/control", "rotation_mode": "weighted", "variants": [ { "destination_url": "https://example.com/a", "weight": 50, "label": "A" }, { "destination_url": "https://example.com/b", "weight": 50, "label": "B" } ] }

rotation_mode controls the strategy:

ValueBehaviour
weighted (default)Per-request random pick proportional to weight
round_robinAtomic Redis counter cycles variants[counter % N]

Round-robin matters when you’re A/B-testing low-volume creatives — weighted random can produce noisy splits at small sample sizes.

Variants are independent of targeting_rules (see Smart links). When both are set, smart links resolve first — a matched rule overrides the variant rotation entirely.

In the dashboard

  • Campaigns at /dashboard/campaigns — create, edit, archive, bulk-assign links.
  • Per-link variants at /dashboard/links/{id} — add variants inline; weight sliders auto-normalise to 100.