Skip to content

Event Schema & Taxonomy

Every event captured by GrowthOS — whether from the client SDK, server API, or internal system — flows through a unified event bus. The bus routes each event to every module that subscribes, enabling cross-module automation without point-to-point wiring.


Every event in GrowthOS follows a standard envelope structure regardless of its source.

{
"id": "evt_abc123",
"type": "track",
"user_id": "usr_123",
"anonymous_id": "anon_xyz",
"event": "feature_activated",
"properties": {},
"context": {
"ip": "203.0.113.1",
"user_agent": "...",
"locale": "en-US",
"page": { "url": "...", "title": "...", "referrer": "..." },
"library": { "name": "@growthos/js", "version": "1.0.0" },
"campaign": { "source": "google", "medium": "cpc", "name": "spring_sale" }
},
"timestamp": "2025-06-01T12:00:00Z",
"received_at": "2025-06-01T12:00:01Z",
"message_id": "msg_unique123",
"tenant_id": "tenant_abc"
}

Envelope fields

id, type, message_id, tenant_id, timestamp, and received_at are present on every event and managed by the platform.

Identity fields

user_id and anonymous_id link the event to a contact. At least one must be present. When both exist, GrowthOS merges them automatically.

Payload fields

event (the name) and properties (arbitrary key-value data) carry the domain-specific information.

Context fields

context is auto-collected by SDKs and includes device, page, campaign, and library metadata.


Consistent naming keeps automations, segments, and analytics reliable across your team.

  1. Use snake_case for all event names and property keys — e.g., feature_activated, plan_name.

  2. Use object.action for domain events — e.g., referral.converted, survey.completed, invoice.paid.

  3. System events start with $ — e.g., $page_view, $session_start. These are emitted by the platform automatically.

  4. Custom events omit the $ prefix — they are developer-defined and free-form within the rules below.

Limits

  • Event name length: 256 characters maximum
  • Properties per event: 256 keys maximum
  • Property value size: 10 KB maximum per value

GrowthOS emits the following system events automatically. You can subscribe to them in automations, segments, and webhooks just like custom events.

EventTriggerKey Properties
$page_viewAuto on page loadurl, title, referrer, path
$session_startAuto on new sessionsession_id, duration
$session_endAuto on session closesession_id, duration, pages
$identifyidentify() calltraits (merged with contact)
$form_submittedAuto on form submitform_id, fields
EventTriggerKey Properties
$referral_link_createdReferral link generatedprogram_id, link_code
$referral_clickedReferral link clickedreferrer_id, link_code
$referral_convertedReferred user convertsreferrer_id, referred_id, reward
EventTriggerKey Properties
$survey_shownSurvey displayedsurvey_id, type
$survey_respondedSurvey submittedsurvey_id, score, answers
EventTriggerKey Properties
$waitlist_joinedWaitlist signupwaitlist_id, position
$waitlist_referredShared waitlist linkwaitlist_id, referrer_id
$waitlist_approvedEntry approvedwaitlist_id, entry_id
EventTriggerKey Properties
$email_sentEmail dispatchedcampaign_id, template_id
$email_openedEmail openedcampaign_id, contact_id
$email_clickedLink clicked in emailcampaign_id, url
$email_bouncedBounce receivedcampaign_id, bounce_type
$email_unsubscribedUnsubscribe actioncampaign_id, reason
EventTriggerKey Properties
$nudge_shownIn-app nudge displayednudge_id, type
$nudge_dismissedNudge dismissednudge_id
$nudge_clickedNudge CTA clickednudge_id, action
$checklist_step_completedOnboarding step donechecklist_id, step_id
$checklist_completedAll steps donechecklist_id
EventTriggerKey Properties
$coupon_redeemedCoupon usedcoupon_code, discount
$upgrade_prompt_shownUpgrade prompt displayedprompt_id, trigger
$upgrade_prompt_clickedUser clicked upgradeprompt_id

The real power of the event bus is cross-module automation — an event in one module triggers actions in others without any custom code.

Source EventConditionAutomated Action
$survey_respondedNPS score is 9 or 10Auto-trigger referral invite email to the promoter
$referral_convertedReferred user completes signupUpdate referrer contact score and send reward email
$waitlist_joinedNew waitlist entryCreate contact, add to waitlist segment, start welcome email sequence
$email_clickedLink clicked in campaignUpdate engagement score on contact; optionally trigger an in-app nudge

Keep names stable

Renaming an event breaks every automation, segment, and funnel that references it. Treat event names as a contract.

Include rich properties

Add enough properties for downstream segmentation — e.g., include plan_name and billing_interval on a subscription.created event.

Use ISO 8601 timestamps

Always send timestamps in ISO 8601 format with UTC offset. The SDK does this by default; server-side callers must ensure it.

No PII in properties

Do not put personally identifiable information (email, phone, name) in event properties. Store PII as traits on the contact via identify() instead.

{
"event": "subscription.created",
"properties": {
"plan_name": "pro",
"billing_interval": "annual",
"mrr_cents": 9900
}
}