funnel engine · Cross Medicine, Inc.

The awababy funnel,
as a pure-function engine.

@awababy/funnel decides when to ask a happy parent for a rating, when to route a struggling one to support, and when the store rating has recovered enough to spend on acquisition. Be bubbly with your baby!

125 tests 96% coverage 0 runtime deps policy · metrics · gate

Session simulator

Every app event flows through step(state, event, now).

session 1 analyses 0 review requests 0 nudges 0

Weekly cohort metrics

The same event log, replayed through the calculator.

CohortUsersActivated ≤7dDay-7 return
CohortOpen→recordCompletionReview req.

The acquisition gate

No paid traffic until the rating recovers.

At ship

Week 8

Where this data comes from

// CryAnalysisViewController.swift — result handler
let event = FunnelEvent.analysisCompleted(
    id: analysisId, confidence: 0.87, category: "hungry")

Telemetry.post(event)               // → POST /api/events

let r = engine.step(state, event, now)
state = r.state                     // persist as JSON
for d in r.decisions {
  switch d {
  case .requestReview:
    SKStoreReviewController.requestReview(in: scene)
  case .showNudge:
    present(SupportSheet(), animated: true)
  }
}

// functions/api/events.js — live on this site
import { validateEvent, step, INITIAL_POLICY_STATE }
  from '../../funnel/index.js'

export async function onRequestPost({ request }) {
  const v = validateEvent(await request.json())
  if (!v.ok) return json({ ok: false, errors: v.errors }, 422)

  // demo: run the shipped engine server-side too
  const r = step(INITIAL_POLICY_STATE, v.event, v.event.ts)
  return json({ ok: true, decisions: r.decisions })
}