Skip to Content
Elido is in closed beta — APIs are stable but rate-limits and quotas may change before GA. Request access →
GuidesConversion tracking

Conversion tracking

A pixel tells you that a click happened. A conversion tells you the click made you money. Elido ingests Stripe and Shopify webhooks, ties each order back to the originating short link, and surfaces revenue in the same dashboard as your click totals.

The flow is:

  1. Add a webhook endpoint at Stripe or Shopify pointing at Elido.
  2. Tag your checkout sessions / orders with the elido_link_id of the link that brought the customer in.
  3. Read attributed conversions from the API.

1. Configure the webhook secret

Each provider gives you a signing secret when you create a webhook endpoint. Store both via the pixels endpoint (it doubles as the secrets vault):

curl -X PUT \ https://api.elido.app/v1/workspaces/1/pixels \ -H "Authorization: Bearer $ELIDO_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "stripe_webhook_secret": "whsec_a1b2c3...", "shopify_webhook_secret": "shpss_a1b2c3..." }'

Webhooks without a configured secret return 401.

2. Point the provider at Elido

In your Stripe Dashboard add an endpoint:

URL: https://api.elido.app/v1/workspaces/1/conversions/stripe Events: checkout.session.completed, payment_intent.succeeded

In Shopify, add an orders/paid webhook:

URL: https://api.elido.app/v1/workspaces/1/conversions/shopify Format: JSON Topic: Order paid

Elido verifies signatures (Stripe-Signature and X-Shopify-Hmac-Sha256 respectively) using the secret from step 1 and rejects mismatches with 401.

3. Tag checkout sessions

Send the originating link_id along with the order so Elido can attribute revenue.

Stripe

Set either metadata.elido_link_id or client_reference_id when creating the checkout session:

await stripe.checkout.sessions.create({ mode: "payment", line_items: [...], success_url: "https://example.com/thanks", cancel_url: "https://example.com/cart", metadata: { elido_link_id: "42" }, });

Shopify

Use note attributes — populate it on the cart from the storefront:

{% comment %} populate from a URL param like ?elido=42 {% endcomment %} <input type="hidden" name="attributes[elido_link_id]" value="{{ elido_id }}">

Elido looks for note_attributes[].name == "elido_link_id" and pulls the corresponding value.

If the link_id is missing the conversion still ingests but with no attribution — link_id and campaign_id are stored as null.

4. Read conversions

curl 'https://api.elido.app/v1/workspaces/1/conversions?limit=50' \ -H "Authorization: Bearer $ELIDO_TOKEN"
{ "conversions": [ { "id": 4711, "platform": "stripe", "external_id": "cs_test_a1b2c3", "link_id": 42, "campaign_id": 7, "revenue_cents": 4900, "currency": "USD", "customer_email": "alice@example.com", "converted_at": "2026-05-01T12:00:00Z" } ], "limit": 50, "offset": 0 }

Pagination is limit (≤100, default 50) + offset. Summary cards:

curl https://api.elido.app/v1/workspaces/1/conversions/summary \ -H "Authorization: Bearer $ELIDO_TOKEN"
{ "total_revenue_cents": 1234500, "currency": "USD", "count": 211, "average_order_cents": 5851 }

What gets attributed

When a webhook arrives, Elido reads the elido_link_id from metadata / note attributes and:

  • Stores it on the conversion as link_id.
  • Looks up the link’s campaign_id and stores that too — campaign attribution is derived, you don’t tag campaigns separately.
  • De-duplicates on (workspace_id, platform, external_id) so retried deliveries don’t double-count.

There’s no UI tagger today — you have to populate the metadata yourself in the checkout integration. Most teams capture the ?elido=... URL param on landing and replay it into the checkout.

Endpoint reference

MethodPath
GET/v1/workspaces/{ws}/conversions
GET/v1/workspaces/{ws}/conversions/summary
POST/v1/workspaces/{ws}/conversions/stripe
POST/v1/workspaces/{ws}/conversions/shopify