PilotFoxDocs

Identify users

POST /api/v1/ingest/identify: link a visitor to a user id with traits, including the email used to link payments.

POST https://pilotfox.app/api/v1/ingest/identify

Tells PilotFox that a visitor is one of your users: their sessions, before and after, then count for that user in the Users report, user filters and retention, and the traits you send are stored on the user's profile. It needs an API key with ingest:write. Reference: POST /api/v1/ingest/identify.

The tracking script has its own identify (pilotfox.identify(...), see Events and identify) for signed-in visitors. The server-side one does the same, with two differences: you say which visitor you mean, and the email trait it sends links payments.

Request

{
  "site": "SITE_ID",
  "uid": "user_8412",
  "ip": "203.0.113.7",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
  "traits": { "email": "ada@example.com", "plan": "pro", "seats": 5 }
}
FieldRequiredWhat it is
siteyesThe site's public id.
uidyesYour user id, up to 255 characters (a number is read as text). An id with no text in it is a 400. Use an id that cannot be guessed, such as a UUID, rather than an email or a counter.
anonymous_idone of the twoYour own stable id for the visitor, as sent with server events.
ip and user_agentone of the twoThe IP address and User-Agent of the visitor's browser, as your server received them: the visitor the browser's own events belong to. Both are needed.
traitsnoAn object of traits to store on the user's profile. A value that is not an object is ignored.

Send anonymous_id, or both ip and user_agent (if all three come, anonymous_id decides). Which visitor each one names is explained in Matching server events to visitors. To identify someone who is browsing your site, use the address and user agent of a request their browser made to your server, for example the sign-in request: that links the visitor the tracking script has been recording.

Traits

  • Values are strings, numbers or booleans. A trait whose value is an object, an array or not a finite number is dropped, and so is one whose key or text holds a NUL character or an unpaired UTF-16 surrogate.
  • Merged, not replaced. Traits you send are added to the profile or overwrite the same keys; keys you leave out stay as they were. To remove a trait, send it with null: { "plan": null }.
  • 4 KB per profile. The stored traits, as compact JSON, are kept within 4 KB. A new or larger trait that would go past it is skipped, and the stored ones are kept.

Response

204 No Content, with no body. It is also the answer when the site's settings exclude the request (an excluded IP address, network, country or user agent, judged on the ip and user_agent you send) or it comes from a detected bot while the site blocks bots: nothing is stored then, and the answer does not say so.

StatusWhen
400 Invalid identifyNo site or uid, an empty uid, an ip that is not an IP address, a user_agent or anonymous_id that is not a string, or neither a non-empty anonymous_id nor both ip and user_agent. (A body that is not JSON is a 400 too, with another message.)
401No API key, an invalid one, or another kind of credential.
403The key lacks ingest:write.
404 Site not foundThe site does not exist, was deleted, or the key cannot write to it (another organization's, outside its site list).
429The key's write budget is spent: identify and events share it.

The email trait and payments

When a payment arrives from a payment provider or the payments API, PilotFox links it to a visit, and so to its traffic source, campaign and affiliate. One way is the customer's email: a payment whose customer email equals the email of a user is linked to that user's latest session before the payment, when no checkout reference or user id linked it first (see Revenue attribution).

Only an email trait sent by this endpoint counts. Anyone can call the tracking script's identify from their own browser with any user id and any email, so an email set that way is shown on the profile but never links a payment. Editing a user's traits in the dashboard never makes an email link payments either.

  • The email is compared without regard to case.
  • Sending email again replaces it; sending "email": null removes it, and payments stop linking by it. Traits sent without an email key leave it as it is.
  • Since payments go to the user's sessions, identify the user's browser (with ip and user_agent), not only an anonymous_id your server made up: a user with no session gets no payment linked.

A complete example

At sign-in, your server knows the user and the browser that signed in:

curl -X POST "https://pilotfox.app/api/v1/ingest/identify" \
  -H "Authorization: Bearer $PILOTFOX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "site": "SITE_ID",
    "uid": "user_8412",
    "ip": "203.0.113.7",
    "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
    "traits": { "email": "ada@example.com", "plan": "pro", "seats": 5 }
  }'

The answer is 204. The user's sessions from that browser now carry user_8412, the profile has the three traits, and a payment with the customer email ada@example.com (in any case) can be linked to that user.

Calling pilotfox.identify("user_8412") in the browser as well does no harm: both name the same user, and only the server call makes the email link payments.

On this page