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 stores a set of UTM defaults, 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 is stored on the campaign for reporting and for your own tagging. Automatic inheritance of these fields into the destination URLs of assigned links is planned, not available yet (see UTM templates); until then, tag destination URLs yourself or with the dashboard UTM builder.

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.