Tracking actions in context

The single biggest instrumentation decision is how you name events and where you put context. Get it right and one event answers a dozen questions; get it wrong and your catalog explodes into hundreds of near-duplicate names that no funnel can line up. This guide is the canonical Kixo pattern — the same design the AI instrumentation advisor (suggest_instrumentation in chat) recommends.

The pattern: one generalized event + rich properties

Track one event per user action and describe the context with properties — never fork the event name per context. A post opened from search and a post opened from the feed are the same action (post_opened) with a different source property.

Anti-pattern

Do not create post_opened_from_search, post_opened_from_feed, post_opened_from_profile. Three event names mean three things to maintain, no single funnel can span them, and adding a fourth surface means a code change everywhere. One post_opened with source scales to any number of surfaces for free.

Don't (event-per-context)Do (one event + property)
post_opened_from_search
post_opened_from_feed
post_opened with { source: "search" | "feed" }
video_played_mobile
video_played_web
video_played — platform is already on every event automatically
checkout_from_cart
checkout_from_buy_now
cart_checked_out with { source: "cart" | "buy_now" }

Naming: snake_case (object)(verb), past tense

Name every event (object)_(verb) in snake_case, past tense — post_opened, video_played, cart_checked_out. The same name must be used verbatim across Web, iOS, and Android so cross-platform funnels line up, and so Kixo's standard-event detector can match canonical names.

  • Object first, verb second — groups related events together when you scan the catalog (post_opened, post_liked, post_shared).
  • Past tense — an event records something that happened.
  • snake_case — not postOpened, not PostOpened. The detector and vocabulary matcher are case-insensitive but converging on one form keeps funnels clean.

Event properties vs user properties

The other half of the decision is where a value lives.

Event propertyUser property
DescribesThis one occurrence of the actionThe person, durably across all their events
Set withKixo.track(name, { ... })Kixo.setUserProperty(key, value)
Examplessource, screen, post_id, amount_centsplan, vip, signup_cohort, lifetime_orders
PowersPer-step funnel filters, breakdowns, distributionsSegmentation, audience targeting, campaign eligibility

Tip

Rule of thumb: if the value can differ between two events from the same user (which post, whichsource), it's an event property. If it's a fact about the user that holds regardless of the action (their plan, whether they're a VIP), it's a user property. Put source on the event; put plan on the user.

Always carry a stable entity id

Pass a stable id for the object the action touched — post_id, video_id, order_id. Without it you can count how many posts were opened, but you can't group, dedupe, or chain events about the same post. A funnel like search → open-from-search → like only resolves to a coherent user journey when each step carries the property that ties the steps together.

Worked example: search → open → like

Say you want to know how many users search, then open a post from the search results, then like it. Three events — but the "from search" context is a source property on post_opened, not a separate event:

  • search_performed{ query }
  • post_opened { source: "search", screen, post_id }
  • post_liked { source: "search", screen, post_id }

Then your funnel filters step 2 (and step 3) on source = "search" — one property predicate, no event-name juggling. The exact SDK calls for each platform:

// User runs a search
Kixo.track('search_performed', {
  query: 'running shoes',
});

// User taps a result — the post was opened FROM search
Kixo.track('post_opened', {
  source: 'search',          // ← context as a property, not the event name
  screen: 'search_results',
  post_id: 'post_8f3a1c',
});

// User likes the post they opened from search
Kixo.track('post_liked', {
  source: 'search',
  screen: 'post_detail',
  post_id: 'post_8f3a1c',
});

Tagging the user instead

If "has liked a post from search" is a durable trait you want to segment on (not just a per-event signal), set a user property after the action: Kixo.setUserProperty("liked_from_search", true). Now the audience explorer and campaign eligibility can target those users directly.

Let the AI design it for you

In the Kixo dashboard chat, describe what you want to measure in plain English — "track posts opened from search and then liked" — and the assistant returns the recommended events, properties, and copy-paste snippets for all three platforms, and tells you which events are already flowing for your project versus what still needs SDK work. It applies exactly the pattern on this page.

See also: the Events Reference for the eleven canonical event names Kixo recognises automatically, and the per-platform SDK guides for Web, iOS, and Android.