Two ways in
Browser tracking -POST /v1/track. The public receptor for engagement
events from your sites and apps, authenticated with a publishable
ek_live_… key (like an analytics measurement id - origin allowlist and
rate limits bound abuse, not secrecy). Events are batched, up to 20 per
request, and accepted per-item: the response tells you for each event whether
it was accepted, a duplicate (already seen via its client-supplied
event_id), or rejected with a reason. This is the surface the
engagement SDK wraps.
Server ingest - POST /v1/ingest. Installed modules push events
server-to-server with an mk_live_… credential and HMAC request signing.
Only relevant if you’re building a 4D module.
Anatomy of an engagement event
An engagement event is deliberately simple:- who - the member, identified by your id for them
(
member_external_id) or the platformuser_id. Events are only recorded for known members; an event that can’t be attributed to one is rejected, not stored. - what - an
action(defaults toengage; e.g.content_view) plus freemetadata. - tags - up to 10 lowercase tags per event
(
world_cup_26,england,kane). Tags are the currency of the engagement system: every event increments the member’s per-tag affinity counters, so over time you get a live map of what each member cares about. Normalization is strict (trimmed, lowercased) soWorld_Cup_26andworld_cup_26converge on one counter instead of fragmenting it. - when - an optional client timestamp, clamped server-side to the recent past.
event_id
with each event and the server dedupes on it, so network retries never
double-count affinity.
What happens next
Accepted events are written to your organization’s event stream and simultaneously published onto 4D’s internal event bus as canonicalengagement.* events. That’s where the rest of the platform picks them up -
most importantly the XP engine, which evaluates your
organization’s rules against each event and awards XP when one matches.
Webhook subscriptions and recent-event queries (30-day retention) are
available for pulling events back out.
Consent-gated enrichment
Events are enriched only as far as the member has consented. The concrete example: if (and only if) the member holds an activedata.geo consent, the
platform stamps a coarse country/region onto their events, derived
transiently from the request - the raw IP address is never persisted. No
consent, no location. See Consent.