Why this matters
The single most important question in early-stage SaaS analytics: what’s the action that, once a user takes it, predicts they’ll stick around?
For Slack it was sending 2,000 messages. For Facebook it was 7 friends in 10 days. For Notion it’s reportedly creating 5 pages. Every successful product has this — and finding it shifts your entire onboarding strategy because suddenly there’s a single bar to clear.
Most teams never answer this question because it requires:
- A 30-day retention definition
- Cohorting users by first-24h behavior
- Running retention per cohort
- Comparing lift
That’s 3 SQL queries and a spreadsheet. Or one prompt to Agentry.
What you get
- The top 3 actions ranked by retention lift
- Conversion + retention curves for each cohort
- A saved cohort definition for “activated users” that the rest of Agentry can use (cohort-based feature flags, surveys, etc.)
Walk through it
What action in the first 24h after signup correlates highest with users being active 30 days later?
Two definitions I need to lock in:
- “Active at day 30” → I’ll use “fired any event between days 28-31”. OK?
- First-24h actions → I’ll look at events fired within 24h of
signup_completed.
Pulling the event vocabulary first.
agentry_list_event_names {
project_id: "default",
min_count: 100
}
{
"events": [
"$pageview", "signup_completed", "first_project_created",
"team_member_invited", "first_query_run", "integration_connected",
"tutorial_completed", "subscription_started", "comment_added", "..."
]
}
Running cohort retention analysis.
agentry_analytics_query {
project_id: "default",
hogql: "
WITH
cohorts AS (
SELECT
person.id AS person_id,
min(timestamp) FILTER (WHERE event = 'signup_completed') AS signup_ts,
array_agg(DISTINCT event) FILTER (WHERE timestamp <= signup_ts + INTERVAL 24 HOUR) AS first_day_events
FROM events
WHERE event = 'signup_completed' AND timestamp > now() - INTERVAL 60 DAY
GROUP BY person.id
),
retained AS (
SELECT person_id, count() AS day_30_events
FROM events
WHERE timestamp BETWEEN now() - INTERVAL 31 DAY AND now() - INTERVAL 28 DAY
GROUP BY person_id
)
SELECT
arrayJoin(first_day_events) AS first_day_event,
count(DISTINCT cohorts.person_id) AS cohort_size,
countIf(retained.day_30_events > 0) AS retained_count,
retained_count / cohort_size AS retention_rate
FROM cohorts LEFT JOIN retained USING (person_id)
GROUP BY first_day_event
HAVING cohort_size >= 50
ORDER BY retention_rate DESC
LIMIT 10
"
}
{
"rows": [
{ "first_day_event": "integration_connected", "cohort_size": 142, "retention_rate": 0.78 },
{ "first_day_event": "team_member_invited", "cohort_size": 98, "retention_rate": 0.71 },
{ "first_day_event": "first_query_run", "cohort_size": 320, "retention_rate": 0.64 },
{ "first_day_event": "first_project_created", "cohort_size": 480, "retention_rate": 0.51 },
{ "first_day_event": "$pageview", "cohort_size": 620, "retention_rate": 0.18 },
{ "first_day_event": "tutorial_completed", "cohort_size": 84, "retention_rate": 0.16 }
]
}
Found it. Top activation candidates:
| Action in first 24h | Cohort | Day-30 retention |
|---|---|---|
| Connected an integration | 142 users | 78% |
| Invited a teammate | 98 users | 71% |
| Ran their first query | 320 users | 64% |
| Created a project (only) | 480 users | 51% |
| Just visited pages | 620 users | 18% |
| Completed the tutorial | 84 users | 16% (!) |
Two strong signals:
-
integration_connectedis your magic moment. Users who connect an integration in the first day retain at 78% — 4.3x better than pageview-only users. Push hard on this in onboarding. -
tutorial_completedis a NEGATIVE signal (16% retention). Users who complete the tutorial don’t actually use the product — the tutorial is a substitute for real engagement, not a path to it. Consider removing it or making it lighter-touch.
Want me to save “connected integration in first 24h” as a cohort called activated_users? You can then use it for targeted feature flags, surveys, churn analysis.
The output
🎯 Magic activation moment found
Top action by retention lift (first-24h → day-30 active):
1. integration_connected 78% (4.3x baseline)
2. team_member_invited 71% (3.9x baseline)
3. first_query_run 64% (3.5x baseline)
Negative signal:
tutorial_completed 16% (below baseline 18%)
→ tutorial is replacing real engagement, not feeding it
Saved cohort: `activated_users` = "connected an integration within 24h of signup"
Use it in: agentry_create_feature_flag, agentry_create_survey,
agentry_analytics_query (`WHERE cohort = 'activated_users'`)
Next moves:
• Onboarding: make integration setup the primary CTA on day 1
• Tutorial: A/B test removing it for new signups
• Email: 24h-later nudge to integrate, with one-click suggestions
Setting it up
You need two kinds of events:
- A
signup_completedevent (or equivalent — the agent matches by intent) - Other events captured in the first 24h that are candidates for “the magic action”
Both should have distinct_id set so cohorts work. Agentry has no SDK — everything is a raw POST to /v1/analytics/. The tiny sendAnalytics helper below is the kind of thing your agent generates at install time (~25 lines, edit freely):
// Agentry.ts — generated by your agent at install time. NOT an SDK.
const DSN = process.env.AGENTRY_DSN!;
const PROJECT_ID = process.env.AGENTRY_PROJECT_ID!;
const UA = "myapp/1.0"; // REQUIRED — Cloudflare 403s default UAs
export async function sendAnalytics(body: unknown) {
await fetch(`https://api.agentry.sh/v1/analytics/${PROJECT_ID}/`, {
method: "POST",
headers: {
"Authorization": `Bearer ${DSN}`,
"Content-Type": "application/json",
"User-Agent": UA,
},
body: JSON.stringify(body),
});
}
// Signup completion — set user properties via $set on the same event
await sendAnalytics({
event: "signup_completed",
distinct_id: user.email,
properties: { $set: { signup_date: new Date().toISOString() } },
});
// Candidate activation events — instrument generously, the agent figures
// out which one matters
await sendAnalytics({
event: "integration_connected",
distinct_id: user.email,
properties: { provider: "github" },
});
await sendAnalytics({
event: "team_member_invited",
distinct_id: user.email,
properties: { count: 1 },
});
await sendAnalytics({
event: "first_query_run",
distinct_id: user.email,
properties: { query_id: q.id },
});
await sendAnalytics({
event: "first_project_created",
distinct_id: user.email,
properties: { project_id: p.id },
});
The more candidate events you capture, the better the agent’s analysis. Don’t worry about overcapturing — Agentry’s pricing is reasonable on volume, and unused events cost nothing to query later.
Variations
- “Same analysis but split by paid vs free signups — does the activation moment differ?”
- “What’s the activation moment for users who came from organic search vs paid ads?”
- “Look at the 90-day retention version — does the same moment hold up over a longer window?”
- “For users who hit the magic moment, what was the most common SECOND action they took? That’s the day-2 nudge target.”