Custom events
Track signups, purchases and refunds from your site with dzati.track().
Beyond pageviews, Dzati can record your most important conversion events so you can tie signups and revenue back to the traffic that earned them.
In this first release we support three custom events:
- signup — someone creates an account or becomes a lead
- purchase — a completed sale (records revenue)
- refund — money returned for an order (reduces revenue)
Setup — add this snippet to send events
To send custom events you need one small snippet in addition to your install script tag. Add it once, before your event code — the <head> is the ideal spot:
<!-- Your Dzati install tag (already on your site) -->
<script defer data-site="DZ-XXXXXXXX" src="https://e.dzati.com/d.js"></script>
<!-- Required for custom events — makes dzati.track() ready immediately -->
<script>
window.dzati = window.dzati || function () { (window.dzati.q = window.dzati.q || []).push(['call', arguments]); };
['track','identify','pageview'].forEach(function (m) {
window.dzati[m] = window.dzati[m] || function () { (window.dzati.q = window.dzati.q || []).push([m, arguments]); };
});
</script>The tracker script loads with defer, so it finishes loading after your page has rendered — which means a dzati.track() call that runs while the page is loading would otherwise be lost. This snippet makes dzati.track() available the instant your page runs: it safely queues your calls and the tracker replays them the moment it's ready. So you can call dzati.track(...) anywhere, at any time, and nothing is missed.
The API
Every custom event is sent with a single call:
dzati.track(eventName, data);
eventName— one ofsignup,purchase, orrefund.data— an object with the event's fields (shown for each event below).
You never pass a visitor or session id. The tracker attaches those automatically from the visitor's first-party cookie — the same identity used for your pageviews — so every signup and sale is attributed to the right visitor and traffic source.
How we prevent duplicates
A page reload, a retry, or a repeat call can send the same event twice. Dzati de-duplicates using the key you provide, so the same action is counted once — even across reloads, different devices, or days apart:
- purchase — deduplicated by
order_id. - refund — deduplicated by
refund_id(ororder_idif you don't send one). - signup — deduplicated by
user_idwhen you provide it (otherwise every signup call is recorded).
These keys are only ever matched against themselves, so they never collapse genuinely different actions together — the same browser can sign up two separate accounts, or place two real orders, and both are counted. Send the right key and you don't have to think about duplicates.
Amounts and currency
- value_cents is the amount in the smallest currency unit — cents for USD/EUR, pence for GBP. So $49.00 is
4900. - currency is an optional 3-letter ISO code such as
USD. If you omit it, your site's default currency is used. - For refunds, send value_cents as a positive number — Dzati records it as a deduction for you.
signup
Track when a visitor creates an account or becomes a lead.
dzati.track('signup', {
user_id: 'john.doe@google.com',
plan: 'pro',
method: 'google',
referral_code: 'LAUNCH20'
});All fields are optional:
- user_id (string) — your own id for the new account: an internal id, username, or email. When you send it, Dzati counts one signup per user_id, so a page reload or a repeat call won't double-count. It's matched only against itself, so the same browser can create two different accounts and both are counted. Without it, every signup call is recorded as-is.
- plan (string) — the plan or tier chosen, e.g.
pro. - method (string) — how they signed up, e.g.
email,google,github. - referral_code (string) — an acquisition or referral code.
You can include any other fields you like; they are stored alongside the event.
purchase
Track a completed sale. This records revenue and attributes it to the visitor's first touch.
dzati.track('purchase', {
order_id: 'ORD-10492', // required
value_cents: 4900, // required — $49.00
currency: 'USD', // optional
plan: 'pro',
coupon: 'LAUNCH20'
});Required:
- order_id (string) — your unique order reference. Used to prevent double-counting.
- value_cents (integer) — the total amount charged, in the smallest currency unit.
Optional:
- currency (string) — ISO code; defaults to your site's currency.
- plan, coupon (string) — descriptive tags you can break revenue down by.
- items (array) — the line items in the order (see below).
Multiple items
Pass an array of items. Each item takes sku, name, qty, and price_cents (the per-unit price):
dzati.track('purchase', {
order_id: 'ORD-10492',
value_cents: 7900, // the actual total you charged
currency: 'USD',
items: [
{ sku: 'PRO-ANNUAL', name: 'Pro annual', qty: 1, price_cents: 4900 },
{ sku: 'SEAT', name: 'Extra seat', qty: 2, price_cents: 1500 }
]
});refund
Track money returned to a customer. A refund reduces the revenue and lifetime value of the original order.
dzati.track('refund', {
order_id: 'ORD-10492', // required — the order being refunded
value_cents: 4900, // required — amount refunded (positive)
currency: 'USD',
reason: 'customer_request'
});Required:
- order_id (string) — the order this refund belongs to.
- value_cents (integer) — the amount refunded, as a positive number.
Optional:
- refund_id (string) — a unique id for this refund. Send it whenever an order can have more than one refund (for example, partial refunds).
- currency (string) — defaults to your site's currency.
- reason (string) — e.g.
customer_request,fraud,duplicate.
Refunding one item from an order
For a partial refund, send the amount being returned plus a refund_id, so several refunds against the same order are each counted:
dzati.track('refund', {
order_id: 'ORD-10492',
refund_id: 'RF-558', // distinguishes this refund
value_cents: 1500, // the one seat
currency: 'USD',
reason: 'customer_request',
items: [{ sku: 'SEAT', name: 'Extra seat', qty: 1, price_cents: 1500 }]
});A second partial refund on the same order just uses a different refund_id, such as RF-559.
Good to know
- Any fields beyond the reserved ones (
order_id,value_cents,currency,refund_id) are stored as free-form properties. Keep them small — up to about 25 keys per event. - Don't put personal data (emails, phone numbers, card details) in event properties.
- Events fired from
localhostand staging hosts are ignored unless you enabled dev mode on the tracker. - Using a template engine that treats
{ }or{{ }}as code (WHMCS/Smarty, Handlebars, and many PHP carts)? Wrap any inline<script>that callsdzati.track(...)in the engine's raw block — in WHMCS/Smarty that's{literal} … {/literal}— or add it through your platform's custom-code field, so the braces in your event data aren't parsed away.
dzati.track() calls that fire before the tracker has finished loading, so you don't have to worry about where your event code sits relative to the script tag.Was this helpful?
Still stuck? Email support