Skip to content

Insights

Behavioral analytics computed from your event stream — included on every plan. Dashboard → Insights, or the API.

Funnels

Sequential conversion between 2–5 events, ordered and windowed — step N counts subscribers who did it after their first step-N−1 event, within the window:

GET /v1/apps/:appId/insights/funnel?steps=signup,activate,purchase&window=72&days=30

Cohort retention

Weekly acquisition cohorts × weekly activity — the classic retention grid:

GET /v1/apps/:appId/insights/cohorts?weeks=8

RFM segments

Recency / Frequency / Monetary scoring over 90 days of activity (monetary = meta.amount on purchase events), quintile-scored and mapped to the classic segment names — Champions, Loyal, Promising, At risk, Hibernating, Needs attention:

GET /v1/apps/:appId/insights/rfm?monetaryEvent=purchase

Campaign-level measurement

  • Funnel per campaign: GET /campaigns/:id/stats
  • A/B variants + winner: GET /campaigns/:id/variants
  • Conversion attribution: GET /campaigns/:id/outcomes?event=purchase&window=24
  • Journey stats: GET /journeys/:id/stats

Predictive bands

The scheduler refreshes two auto-managed tags hourly from the last 90 days of events:

TagBandsMeaning
_churn_risklow / medium / highLast activity within 7 days / 7–21 days / silent 21+ days
_engagementhigh / medium / low≥8 opens+clicks in 90d / 2–7 / ≤1

Subscribers with no activity at all get no bands — you can't churn from a relationship that never started.

Because they're ordinary tags, they work everywhere tags do with no new syntax: segment filters ({ key: "_churn_risk", op: "eq", value: "high" } targets a win-back campaign), journey condition branches, and Liquid. GET /v1/apps/:id/insights/predictive returns the band distribution, also shown on the dashboard's Insights page. The banding is transparent statistics, not a black box — thresholds are documented above and will evolve behind the same tags.

Warehouse export (BigQuery)

Postgres stays the system of record; set EVENTS_BIGQUERY_DATASET + EVENTS_BIGQUERY_PROJECT (or GOOGLE_CLOUD_PROJECT) on the ingest and worker services and every event — SDK beacons, custom events, delivery receipts — is also streamed to BigQuery dataset.events (columns: app_id, type, subscriber_id, device_id, campaign_id, ts, meta). Mirroring is best-effort by design: a warehouse outage never fails ingestion.

Backfill history with pnpm backfill-bigquery [--app id] [--days 90]. Create the table first:

sql
CREATE TABLE engage.events (
  app_id STRING, type STRING, subscriber_id STRING, device_id STRING,
  campaign_id STRING, ts TIMESTAMP, meta STRING
) PARTITION BY DATE(ts);

Data hosted in Southeast Asia (asia-southeast1).