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:
- Add a webhook endpoint at Stripe or Shopify pointing at Elido.
- Tag your checkout sessions / orders with the
elido_link_idof the link that brought the customer in. - 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.succeededIn Shopify, add an orders/paid webhook:
URL: https://api.elido.app/v1/workspaces/1/conversions/shopify
Format: JSON
Topic: Order paidElido 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_idand 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
| Method | Path |
|---|---|
GET | /v1/workspaces/{ws}/conversions |
GET | /v1/workspaces/{ws}/conversions/summary |
POST | /v1/workspaces/{ws}/conversions/stripe |
POST | /v1/workspaces/{ws}/conversions/shopify |