Events & tracking
Send events with track(): standard events, custom events, and revenue.
track() on the @opinly/backend client records a server-side
event. The name can be anything: pick a standard event if one fits, or make your
own.
It runs with your secret sk- key. Page views, form fills, and identify are already handled in the
browser by the pixel (publishable pk- key), so you don't send those
yourself.
Sending a purchase from your server? Read
Linking server events to browser visitors first — passing
anonId or email is what ties the sale back to the campaign that earned it. Without one, the
revenue is recorded but shows up as "direct".
track
import { createOpinlyClient } from '@opinly/backend'
const opinly = createOpinlyClient()
await opinly.track('sign_up', { method: 'google' }, { email: 'user@example.com' })
await opinly.track(
'purchase',
{ value: 49.0, currency: 'USD' },
{ externalEventId: 'order_123', email: 'user@example.com' },
)| Argument | |
|---|---|
event | The event name, standard or custom. |
properties | Data to attach. Revenue events need value (major units) and currency. |
opts.externalEventId | Dedup key. Two calls with the same id become one event, so retries are safe. |
opts.email | Ties the event to a visitor. We hash it; the raw email is never stored. |
opts.anonId | The visitor's Opinly id, read from window.opinly.anonId in the browser and passed to your server. See Linking server events. |
Standard events
Any name works, but these are the ones worth knowing. They line up with GA4, Meta, and Segment, so the
data maps over without translation. Revenue comes from value + currency; every other property is
stored as-is.
| Event | When to send it | Common properties | Revenue |
|---|---|---|---|
purchase | Order completed | value, currency, transaction_id, items | yes |
refund | Order refunded | value, currency, transaction_id | yes |
add_to_cart | Item added to cart | value, currency, items | |
remove_from_cart | Item removed | value, currency, items | |
begin_checkout | Checkout started | value, currency, items, coupon | |
add_payment_info | Payment details entered | value, currency, payment_type | |
view_item | Product viewed | value, currency, items | |
search | Search run | search_term | |
sign_up | Account created | method | |
login | User logged in | method | |
generate_lead | Lead or contact submitted | value, currency | |
start_trial | Trial started | plan, value, currency | |
subscribe | Subscription started | plan, interval, value, currency |
Only purchase and refund become revenue. A value on anything else stays a plain property.
Want autocomplete? Import the list:
import { STANDARD_EVENTS, type StandardEvent } from '@opinly/backend'trackPurchase
Shorthand for a purchase:
await opinly.trackPurchase({
orderId: 'order_123',
value: 49.0,
currency: 'USD',
email: 'user@example.com',
})Reserved names
The pixel fires these itself, or they're reserved for system use, so the API rejects them with a
400:
page_view, page_leave, click, form_submit, identify, session_start, scroll, and anything
starting with $.