# Conversions you define, recorded once

> You decide what counts: page rules, a track() call, a server events API or webhooks from booking, payment and form tools, each with a funnel stage and a value, and leads forwarded to your CRM, Slack, a sheet or a webhook.

A conversion is whatever completes a step in your funnel: a thank-you page, a booked call, a paid invoice, a lead your product qualified. Define it once with a stage and a value, detect it from your pages, your servers or your tools, and it feeds attribution, the optimiser, the ad platforms and your CRM.

## Five ways to detect a conversion

Any one rule completes the conversion. Page rules need nothing beyond the tracker snippet.

| Rule | Example | Where it runs |
| --- | --- | --- |
| Thank-you page | URL starts with /thank-you, is exactly /signup/done, or matches a pattern | On the server, against page views |
| Form submit | Form id or name contact, or a CSS selector such as #signup-form | On the server (id or name) or in the page (selector) |
| Click | A CSS selector such as .book-demo, or a link to your booking page | In the page |
| Named event | signup_completed | demander.track() or the server events API |
| Integration | Calendly invitee.created, Stripe checkout.session.completed, a Typeform form, HubSpot meetings, a native lead form, the hosted form | Webhooks, the CRM sync, lead form polling |

Patterns are limited to 200 characters and may not use nested quantifiers, backreferences or lookbehinds, so a rule can never slow a page down. Test sends an event through the whole pipeline; it shows under live events and is never counted, attributed or uploaded.

## What a conversion definition holds

- **Kind.** Sign-up, registration, booking, form, purchase, trial start, qualified lead or custom.
- **Counts as.** The funnel stage it represents: lead, MQL, SQL, opportunity or customer. The company moves forward to that stage and never back. A booking counts as a meeting, which moves the company into sales.
- **Value and counting.** A fixed value, the value sent with the event, or none, with a currency. Counted once per person, once per company or every time.
- **Window and goals.** How far back touches get credit (90 days by default), whether it is a primary goal, and whether it is sent to the ad platforms.

## From the browser

```js
demander.track('signup_completed', { value: 49, currency: 'EUR', event_id: 'order-1042', plan: 'pro' });
```

value, currency and event_id are always allowed. Send the same event_id to your ad pixel and the platforms deduplicate browser and server events. Up to 20 other flat properties, sent in strict mode only after analytics consent; keys and values that look like personal data are dropped in the browser and again on the server.

## From your servers

```bash
curl -X POST https://app.demander.to/v1/events \
  -H 'Authorization: Bearer dsk_…' -H 'Content-Type: application/json' \
  -d '{"event_id":"order-1042","event":"signup_completed","value":49,"currency":"EUR",
       "anonymous_id":"<demander.anonymousId()>","email":"jana@acme.cz",
       "consent":{"marketing":false,"ad_user_data":true}}'
```

Each site has its own secret key, shown once and stored only as a hash. Up to 50 events per request; repeating an event_id returns duplicate, so retries are safe. The e-mail finds or creates the contact and is never stored on the conversion.

## Webhooks from your tools

Connect a tool to get its webhook URL, then add an integration rule to the conversion it completes.

| Tool | Events | Verified by |
| --- | --- | --- |
| Calendly | Invitee created and cancelled | Calendly’s webhook signature |
| Cal.com | Booking created and cancelled | X-Cal-Signature-256 |
| Stripe (your own account) | Checkout completed, invoice paid, refunds | Stripe-Signature with your webhook secret |
| Shopify | Order created, paid and cancelled | Shopify’s HMAC header |
| Typeform, Tally | Form responses | Their signature headers |
| Jotform | Submissions | The secret URL itself, since Jotform signs nothing |
| Any other tool | Your JSON with event_id, event and the server API fields | X-Demander-Signature (HMAC-SHA256) |

A cancelled booking or a refund cancels the conversion it names. Deliveries are deduplicated by the tool’s id, so retries are harmless. Click ids and hashed e-mails from a tool reach ad platforms only if you confirm the tool collects consent for ad measurement.

## Hosted forms and lead destinations

- **Hosted form.** A Demander-hosted form per conversion that asks only for the fields you list, with a honeypot and rate limits. Its opt-in box sends a double opt-in e-mail; the form itself never records consent.
- **Native lead forms.** Meta Instant Forms and LinkedIn Lead Gen Forms created with the campaign, read back every 15 minutes in live mode.
- **Lead forwarding.** Every conversion with lead details can go to your CRM (contact, company by domain and a note), e-mail to chosen people, Slack, a signed webhook, a Google Sheet that Demander creates, or your existing form endpoint. See [lead destinations](https://demander.to/platforms/lead-destinations/).
- **Only what the person gave.** Only the fields the person entered are forwarded, renamed and limited by your field mapping. Failed deliveries retry after 1, 5 and 30 minutes, then 2 and 12 hours. The log keeps status and response codes, never the lead’s details.

## Where a conversion goes next

Each conversion is recorded once: by its event id first, then by the counting rule. It carries the campaign, ad, creative, message and persona behind it, taken from the UTM parameters the tool passes back, else the visit, else the account’s last campaign touch inside the window. The company gets a signal and moves to the stage the conversion counts as.

In [attribution](https://demander.to/features/attribution/) you can pick opportunities, any primary conversion or one conversion, with cost per conversion per row. A campaign can target cost per conversion or ROAS on one conversion, and the [optimiser](https://demander.to/features/budget-optimisation/) then compares ads and budgets by what Demander measured. Conversions marked for the ad platforms go out hourly to Google, Meta, LinkedIn, Microsoft, TikTok and Reddit under your event id, with click ids only from consented visits and hashed e-mails only with consent.

## Questions

**Do I need a developer?**

For thank-you pages, forms and clicks, no: you set the rules in Demander once the snippet is on your site. Webhooks need the URL pasted into the tool. The track() call and the server events API need a developer.

**How do I keep campaign lineage through Calendly or Typeform?**

Let the tool carry the ad’s UTM parameters. Calendly keeps them automatically, Typeform and Tally need hidden fields named utm_campaign and utm_content, Stripe Checkout can take the visitor’s anonymous id as client reference, and Shopify keeps the landing page URL.

**What stops a conversion from being counted twice?**

The event id comes first, so a retried request returns duplicate. Then the counting rule applies: once per person, once per company or every time. Webhook deliveries are deduplicated by the tool’s own id, and the same event id lets the ad platforms merge pixel and server events.

**Is personal data sent to the ad platforms?**

Only a SHA-256 hash of the e-mail, and only with consent. For people in the EU, the EEA, the UK and Switzerland that means consent to ad measurement (ad_user_data); elsewhere existing e-mail consent also counts. Click ids are sent only from visits with marketing consent. People who used the ads opt-out page, sent Global Privacy Control or said no to ad measurement are left out of uploads entirely. Lead details go to the destinations you set up, never to the ad platforms.

## Related

- [Website tracking](https://demander.to/features/website-tracking/)
- [Attribution](https://demander.to/features/attribution/)
- [Lead destinations](https://demander.to/platforms/lead-destinations/)
- [CRM](https://demander.to/platforms/crm/)
- [Offline conversions](https://demander.to/resources/offline-conversions/)

---
Source: https://demander.to/features/conversion-tracking/ · Demander · reviewed 2026-10-02
