Track Product Usage

Use ripples.track() only for significant product usage — the actions that prove a user got value. Not a generic event log.

ripples.track()

track() is only for significant product usage — the actions that indicate a user got real value from your product (created a budget, sent a message, invited a teammate). It is not a generic event log like PostHog or Mixpanel. Every track() call is counted as meaningful engagement and feeds the Activation dashboard, so noise here directly pollutes your funnel.

Do not send: pageviews, banner impressions, button clicks, modal opens, "viewed X" events, or anything you'd send "just in case." If you're not sure the action represents real product value, leave it out.

ripples.track("created a budget", {
  area: "budgets",
})

Ripples auto-detects activation moments (first occurrence per user per action), computes adoption rates by product area, and correlates usage patterns with retention and payment.

Client-side or server-side?

track() exists in every Ripples SDK and the rules are the same everywhere — only the call site changes.

  • Client-side (ripples.track(...) from the JS SDK, including in Telegram Mini Apps and the iOS SDK) — best for UI-driven actions where the user clicked something and the result is visible to them: created a budget, sent a message, exported a report.
  • Server-side ($ripples->track(...) in PHP, ripples.track(...) in Python) — best for actions that must not be lost: webhook-confirmed signups, background-job completions, anything the browser shouldn't be the source of truth for. Deliveries are batched and retried automatically.

If the same action can be observed from either side, prefer the side closest to the source of truth. A "subscription started" event belongs server-side (driven by Stripe webhook). A "report exported" event can live client-side. Don't double-fire — one action = one event, regardless of where it was sent from.

See PHP SDK and Python SDK for the full server-side reference.

What NOT to track

Ripples is opinionated on purpose — it's the anti-PostHog. Keep these out of track():

  • Pageviews — already captured automatically by the script tag. Call ripples.pageview() only for SPA route changes.
  • Banner / ad / component impressions — "user saw X" is not product usage.
  • Button clicks and modal opens — unless the click completes a meaningful action, don't send it.
  • "Viewed profile," "opened settings," "scrolled to bottom" — navigation, not activation.
  • Debug or diagnostic events — use logs, not track().

The test: would a founder describe this action as "the user got value from my product"? If not, don't track it.

Parameters

Parameter Type Description
name required string What the user did. Be specific: "created a budget", not "budgets".
options optional object Options object with area, activated, and any custom properties.

Options

Key Type Description
area optional string Product area this action belongs to (e.g. "budgets", "sharing"). Groups actions in the dashboard.
activated optional boolean Set to true on the specific occurrence when activation happens for this user. This does not mark the event type as an activation event — it marks this particular moment as when the user activated. For example, "sent message" is a regular event, but when a user sends their 10th message you may consider that their activation moment and send that occurrence with activated: true.
[custom] optional string | number Any additional context. Values should be strings or numbers.

Examples

Finance app

// User created a budget — group under "budgets" area
ripples.track("created a budget", { area: "budgets" })

// User set a spending limit
ripples.track("set budget limit", { area: "budgets", limit: "500" })

// User exported a report
ripples.track("exported report", { area: "reports", format: "csv" })

Personal finance tracker

// User added a transaction — everyday action
ripples.track("added transaction", { area: "transactions" })

// User added their 10th transaction — we consider this their activation moment
ripples.track("added transaction", {
  area: "transactions",
  activated: true,  // only on THIS occurrence, not every "added transaction"
})

// User exported a report
ripples.track("exported report", { area: "reports", format: "csv" })

Product areas

Use the area option to group actions into zones of your product. Areas are auto-discovered from your track() calls — no setup required. They appear in the Activation dashboard as an adoption heatmap:

Product Areas           Adoption    → Paid
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Basic Tracking  ████████████  89%     6%
Budgets         ██████        41%    18%
Sharing         ████          27%    22%
Reports         ██            14%     9%

Activation flag

Use activated: true to mark the specific moment a user activates — not to label an event type as "the activation event."

The same event name can be sent many times without the flag. You add activated: true only on the occurrence that represents the milestone. Your app decides when that is (e.g. 10th transaction added, first budget over $100).

// User added their 10th transaction — we consider this their activation
ripples.track("added transaction", {
  area: "transactions",
  activated: true,  // only on this occurrence
})

// All other "added transaction" calls are normal — no activated flag
ripples.track("added transaction", { area: "transactions" })

Alternative: queue syntax

You can also use the function-call style, which works even before the SDK has loaded:

ripples("track", "created a budget", { area: "budgets" })

Both ripples.track(...) and ripples("track", ...) are equivalent.

Best practices

  • Only track significant usage. Every track() call feeds the Activation dashboard — pageviews, clicks, and impressions pollute it.
  • Be specific with action names"created a budget" is better than "budgets" or "click".
  • Use areas consistently — pick area names that match how your product is organized.
  • Use activated: true on the specific occurrence when you consider the user activated — not on every call of that event type.
  • Events are sent via sendBeacon so they won't block navigation or slow down your site.