Docs
Guides Website tracking Identify visitors and track events

Identify visitors and track events

The tracking snippet records page views by itself. With a few lines of JavaScript it can also tell RadarSend who a visitor is, and record the things they do that matter to you, like a purchase, a signup or a download. Those events land on the contact’s timeline, and you can use them in segments, lead scoring and sequences.

Everything here goes through window._qp, the object the snippet sets up.

Before you begin#

Call it before the snippet has loaded#

The snippet loads with async, so your code can run before it’s ready. To make calls safe at any time, add this short script above the snippet tag. It holds your calls in a queue and the snippet runs them, in order, as soon as it loads.

<script>
  window._qp = window._qp || { _q: [] };
  (function (qp) {
    if (!qp._q) return; // the snippet has already loaded
    'track identify consent purchase addToCart paymentFailure renewal cancellation cancelPending expired reactivation refund meetingBooked signup formSubmit download video login'
      .split(' ').forEach(function (m) {
        qp[m] = qp[m] || function () { qp._q.push([m, [].slice.call(arguments)]); };
      });
  })(window._qp);
</script>
<script src="https://t.example.com/_q/qs.js" data-tenant-key="your-key" async></script>

If you use consent mode, your snippet already starts with a one-line window._qp script. Put this one after it, and keep both above the snippet tag.

Without this script, calling _qp.track() before the snippet loads fails with an error, and the call is lost. If all your calls run later, after a click or a form submission, you can skip it.

Identify a visitor#

When a visitor tells you their email address, on a login, a checkout or a signup form you built yourself, pass it to RadarSend:

_qp.identify('ana@example.com');

From then on, that browser’s visits belong to that contact, and so do the pages they viewed earlier in the same browser.

  • If a contact already has that address, the visits are connected to it. Nothing about the contact changes: identify() never edits fields, lists or subscriptions.
  • If no contact has it, RadarSend creates a pending contact. A pending contact doesn’t receive email and doesn’t count toward your plan. It becomes active when a trusted source confirms the address, for example a RadarSend form (once the address is confirmed, if the form uses double opt-in), an import, the API, or someone on your team activating it.

identify() runs in the background and returns nothing. Events you send right after it wait until it’s done, so they’re recorded against the right contact.

Note

identify() can’t set fields or subscribe anyone. To save a name, a plan or a consent choice, use a RadarSend form or the Contacts API.

Identify from your server instead#

If your site has its own backend, identifying from the server is the stronger option. Read the visitor’s _emts cookie on your server and send it as session_id when you create or update the contact through the API:

PUT /api/contacts
{ "email": "ana@example.com", "first_name": "Ana", "session_id": "<value of the _emts cookie>" }

That one authenticated call creates the contact as active, saves its fields, and connects the browser’s visits, before and after. See Contacts in the API reference.

Track an event#

_qp.track(name, properties) records anything you want to know about. Give it a name and, optionally, an object of details:

_qp.track('webinar_registered', { webinar: 'Pricing teardown', date: '2026-10-14' });
  • Name. Use one consistent name per kind of thing, such as webinar_registered. Lowercase with underscores is easiest to work with later. Up to 256 characters.
  • Properties. A flat object of strings, numbers and booleans works best. Up to 256 properties.

An event from a visitor RadarSend doesn’t know yet is kept. If they’re identified later in the same browser, it’s added to their contact along with their earlier page views.

Use a ready-made event type#

For common events, use one of the typed methods instead of track(). They record the event with a standard type, so it matches RadarSend’s built-in activities in Settings→Activities with no extra setup, and it’s ready to use in lead scoring, the Triggered an activity segment filter and the Activity occurs sequence trigger.

_qp.purchase({ order_id: 'A-1042', value: 49, currency: 'USD', product_name: 'Annual plan' });
_qp.signup({ plan: 'starter' });
_qp.download({ file_url: '/guides/deliverability.pdf' });
MethodBuilt-in activityUseful properties
purchasePurchaseorder_id, value
addToCartAdd to cartproduct_name
paymentFailurePayment failure
renewalRenewalvalue
cancellationCancellation
cancelPendingCancel pending
expiredExpired
reactivationReactivation
refundRefundorder_id, value
signupSignup
loginLogin
formSubmitForm submittedform_name
downloadDownloadfile_url
videoVideo watched
meetingBookedMeeting bookedscheduled_at

Each method takes one object of properties. The event is named after the method (purchase, add_to_cart, form_submit and so on). To use your own name, add event_name to the object.

A few property names are tidied up for you: total, amount and price become value, and product and product_title become product_name.

Use your events#

  • On the contact. Open a contact and choose the Activity tab.
  • In segments. Under Activities, Triggered an activity matches the typed events above. Custom event matches any event by name. See Build a segment.
  • In lead scoring and sequences. Events recorded with track() don’t match a built-in activity. To score one or start a sequence from it, go to Settings→Activities, click + Add custom activity, choose Generic as the Activity type, and enter the event name under Event name. It then appears in the Activity occurs trigger. See Sequence triggers.

Common issues#

  • _qp is not defined, or _qp.track is not a function. Your code ran before the snippet loaded. Add the queue script from Call it before the snippet has loaded.
  • An event isn’t in the Custom event filter’s Event name list. Once your server has sent events through the API, that list shows the names it has seen, and a name sent only from the browser may be missing. Use Triggered an activity with a custom activity for that name instead (see above).
  • Events show on an anonymous visitor, not the contact. The visitor hasn’t been identified in this browser yet. Call _qp.identify() when they sign in or check out, or identify them from your server.
  • Nothing is recorded at all. Check that the snippet is on the page and its data-tenant-key is right. See Add tracking to your website.

Good to know#

  • Don’t use the names active_time, scroll_milestone or interaction_proof for your own events. The snippet uses them to measure engagement, and RadarSend doesn’t record them as events.
  • Events from known bots are dropped, and events in a visit that RadarSend classifies as a bot are marked that way.
  • identify() is limited to 30 calls a minute from one IP address, so visitors sharing a network (an office, a mobile carrier) share that limit. Each day, it creates at most 1% of your plan’s contact limit in new pending contacts (never fewer than 25). Addresses past that limit aren’t created.
  • To record events from your backend, such as a renewal your billing system processes, use the Events API.