Docs·Tracking

POST/1.0/track/identify

Identify a visitor

Ties a visitor, meaning one browser, to a person, found by email address. From then on, that browser's visits and events, the earlier ones included, count for the person. Someone who signs in on their phone and their laptop is counted once, and appears on the Profiles page under their email with the details you send in attributes.

Where the tracking script runs, call Spreelytics.identify(email, attributes) when someone signs up or signs in, and the script sends this request for you (see Identify users). Call the route yourself where the script cannot run, or from your server with the visitor id the browser handed it.

The request

POST https://sdk.spreelytics.com/1.0/track/identify, in either encoding:

  • Form, as the script sends it: Content-Type: application/x-www-form-urlencoded, with a clientKey field holding your client key and a data field holding the JSON object below as a string.
  • JSON: Content-Type: application/json, the JSON object below as the body, and the key in the address: ?clientKey=YOUR_CLIENT_KEY. Leave clientKey out of the JSON body. This route does not accept the field and answers 400.

Your client key is in Settings → API keys, under Site tracking key. Getting started covers both encodings in more detail.

Fields

FieldTypeRequiredWhat it is
visitorIdstringYesThe browser to tie to the person, the same id its pageviews carry. On a page that runs the script, Spreelytics.getVisitorId() returns it.
identifiersobjectYesHolds the email address: { "email_id": "ada@example.com" }.
identifiers.email_idstringYesThe person's email address. See The email address.
attributesobjectNoDetails to save on the person. See Person attributes.

This route takes no sessionId and no timestamp. Sending either one, or any other field, makes the request fail with 400.

The email address

Email is the only way to identify a person. There is no user id or alias form.

Spreelytics does not check the address. The script skips anything that does not look like an email (text, an @, more text, a dot, more text) and sends nothing for it, so check the address yourself before you call the route.

Send the address in lower case, without spaces. An existing person is only found when the address matches exactly, letter case included, and new people are normally stored in lower case. So Ada@Example.com would not find ada@example.com, and a second person would be created instead.

What happens to the visitor

  • If a person with this email exists in the audience, the visitor is tied to them. If not, a new person is created with this email.
  • The visitor's visits and events from before the call now count for that person too, so the visits that led up to a signup appear on the new person's profile.
  • If the visitor was already tied to a person with a different email, it moves to the person you name now. That is what happens when two people sign in on the same computer.
  • If the visitor had never been seen before, it is recorded now, already tied to the person.
  • Calling the route again with the same visitor and email changes nothing but the attributes, so calling it on every sign-in is safe.

Identify calls are not counted as events, and they are not stopped by the hard limit on your plan's allowance.

Person attributes

attributes is an object of details about the person. These keys fill the person's built-in fields, and take text:

KeyField
first_name, last_nameFirst and last name
company, websiteCompany and company domain
phonePhone number
address, address_line2, city, state, zip, countryPostal address
langLanguage

Any other key with a text, number or true or false value is saved as a custom attribute under that key, such as "plan": "growth" or "seats": 5. A value that is null, an object or a list is ignored. A built-in key with a value that is not text, such as a number sent as phone, is saved as a custom attribute instead.

Attributes are saved in the background, shortly after the call answers. A new value replaces the old one. Most built-in fields can also be used in segment rules, under Contact.

What it answers

AnswerWhat it means
200 with an empty bodyAccepted. The link and the attributes are saved shortly after.
200 with the body OKDropped and not stored. See below.
400A required field is missing or has the wrong type, or the body has a field this route does not accept, clientKey included. The JSON answer names each problem under fields.
401 with the body Event API: UnauthorisedNo client key, an unknown client key, or a request from a site that is not in Allowed domains (Settings → Details).
413The body is larger than 250,000 bytes.
500In the form encoding, data is not valid JSON.

A call is dropped, and still answered with 200 and OK, when its User-Agent belongs to a bot, a crawler, a command line tool or an HTTP library (curl, Python's requests, axios, node-fetch and others) or names a headless browser or test tool, and when it comes from an address in the published ranges of Amazon Web Services, Google Cloud, Oracle Cloud, DigitalOcean or Linode. The full rules are in What the Tracking API drops.

Calling it from a server

A common reason to identify from a server is that sign-in happens there. Have the page that starts the sign-in send Spreelytics.getVisitorId() along with the form, then call this route once the sign-in succeeds.

  • Check where your server runs. A request from Amazon Web Services, Google Cloud, Oracle Cloud, DigitalOcean or Linode is dropped, whatever it contains. Vercel and other hosts built on those clouds are included.
  • Send a browser's User-Agent. Your HTTP library's own User-Agent is dropped as a bot. Forwarding the visitor's own is the simplest way to pass the check.
  • Send an Origin header with a hostname from Allowed domains, such as https://www.example.com, or the call is refused with 401.

On a cookieless audience

With cookieless tracking on, the collector ignores the visitorId you send and works out the visitor from the request's address and User-Agent. From the visitor's browser, that is the right visitor. From a server, it is a visitor made from your server's address, so the person would be tied to the wrong one. On a cookieless audience, identify people from the browser.

Request

# curl's own User-Agent is dropped as a tool, so this sends a browser's.
curl -X POST 'https://sdk.spreelytics.com/1.0/track/identify?clientKey=YOUR_CLIENT_KEY' \
  -H 'Content-Type: application/json' \
  -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36' \
  -H 'Origin: https://www.example.com' \
  -d '{
    "visitorId": "vid_6f1c2a4e-8d3b-4c55-9a7e-2b8f0c9d1e23",
    "identifiers": { "email_id": "ada@example.com" },
    "attributes": { "first_name": "Ada", "company": "Acme", "plan": "growth" }
  }'
// In a browser, without the tracking script. These are the ids saved by
// the browser sample on Track a pageview.
const ids = JSON.parse(localStorage.getItem('my_ids'));
const email = 'Ada@Example.com'.trim().toLowerCase();

await fetch('https://sdk.spreelytics.com/1.0/track/identify', {
  method: 'POST',
  body: new URLSearchParams({
    clientKey: 'YOUR_CLIENT_KEY',
    data: JSON.stringify({
      visitorId: ids.visitorId,
      identifiers: { email_id: email },
      attributes: { first_name: 'Ada', company: 'Acme', plan: 'growth' },
    }),
  }),
});
# On your server, after a successful sign-in. visitor_id came from the
# browser (Spreelytics.getVisitorId()).
import requests

requests.post(
    "https://sdk.spreelytics.com/1.0/track/identify",
    params={"clientKey": "YOUR_CLIENT_KEY"},
    headers={
        # The visitor's own User-Agent. The requests default is dropped as a tool.
        "User-Agent": visitor_user_agent,
        # A hostname from Allowed domains.
        "Origin": "https://www.example.com",
    },
    json={
        "visitorId": visitor_id,
        "identifiers": {"email_id": user.email.strip().lower()},
        "attributes": {"first_name": user.first_name, "plan": user.plan},
    },
)

Response

200 OK
(empty body)
  • Identify users: identifying people from the page with the script.
  • Profiles: where identified people and their attributes show up.
  • Track an event: events whose attributes update the person once they are identified.

See your own numbers today.

Free up to 100k events a month · no credit card

Contact

Tell us what you need.

A real person reads these. We usually reply within one working day.

Or email us directly at contact@spreelytics.com.