Why this matters
Lifecycle emails are graded by open rate, click rate, maybe unsubscribe rate. The metric that actually matters — “did they do the thing the email asked?” — requires joining your ESP data to your product data and almost no team does it.
Customer.io, Loops, Resend all give you “X people clicked.” None of them say “X people clicked AND THEN created their first project within 24 hours.” That join needs both sides in one database.
Agentry holds both: send every email open/click as an analytics event (one fetch from your ESP webhook), and join against your in-app events using distinct_id. The agent ships the funnel as a per-template scorecard.
What you get
- A per-email-template funnel:
sent → opened → clicked → in-app target action - Templates ranked by action-conversion rate (not click rate)
- Surprise findings: the email everyone opens but no one acts on, vs the low-CTR email that drives 40% of activations
Walk through it
Build a funnel from onboarding email opens (UTM-tagged) to the in-app action they were supposed to trigger. Per-template breakdown.
Let me see what email events you’ve got and what target actions you’ve defined.
agentry_analytics_query {
project_id: "default",
hogql: "SELECT properties.email_template AS template, count() AS sent FROM events WHERE event = 'email_sent' AND timestamp >= now() - INTERVAL 30 DAY GROUP BY template ORDER BY sent DESC"
}
{
"rows": [
{ "template": "welcome_day0", "sent": 4200 },
{ "template": "create_first_project_day1", "sent": 4180 },
{ "template": "invite_teammate_day3", "sent": 4100 },
{ "template": "feature_overview_day5", "sent": 4050 },
{ "template": "trial_ending_day12", "sent": 3800 }
]
}
agentry_run_recipe {
recipe_id: "email_to_action_funnel",
params: {
project_id: "default",
templates: [
{ name: "welcome_day0", target_action: "signup_completed", window_hours: 24 },
{ name: "create_first_project_day1", target_action: "first_project_created", window_hours: 24 },
{ name: "invite_teammate_day3", target_action: "team_member_invited", window_hours: 48 },
{ name: "feature_overview_day5", target_action: "integration_connected", window_hours: 72 },
{ name: "trial_ending_day12", target_action: "subscription_started", window_hours: 72 }
],
window_days: 30
}
}
{
"templates": [
{ "name": "welcome_day0",
"sent": 4200, "opened": 2940, "clicked": 1188, "target_action": 1080,
"open_rate": 0.70, "ctr": 0.40, "action_rate": 0.92 },
{ "name": "create_first_project_day1",
"sent": 4180, "opened": 2090, "clicked": 418, "target_action": 209,
"open_rate": 0.50, "ctr": 0.20, "action_rate": 0.50 },
{ "name": "invite_teammate_day3",
"sent": 4100, "opened": 2050, "clicked": 615, "target_action": 41,
"open_rate": 0.50, "ctr": 0.30, "action_rate": 0.067 },
{ "name": "feature_overview_day5",
"sent": 4050, "opened": 1620, "clicked": 162, "target_action": 162,
"open_rate": 0.40, "ctr": 0.10, "action_rate": 1.00 },
{ "name": "trial_ending_day12",
"sent": 3800, "opened": 2660, "clicked": 1140, "target_action": 380,
"open_rate": 0.70, "ctr": 0.30, "action_rate": 0.33 }
]
}
Two findings worth your attention:
invite_teammate_day3is the worst. 615 people click, only 41 actually invite anyone. The CTA is broken — likely the click sends them to the workspace home, not to the invite modal. Fix the deep link.feature_overview_day5is the surprise. Only 10% CTR but 100% of clickers do the target action. The email is filtering out un-interested users; those who click are pre-qualified. Don’t fix the CTR, leverage it.trial_ending_day12has good open/click but only 33% conversion to subscription. Pricing or friction at checkout. Worth a separate investigation.
agentry_publish_query {
recipe_id: "email_to_action_funnel",
description: "Onboarding email → in-app conversion (30d)",
params: { window_days: 30 }
}
Dashboard published. The actionable list: fix invite_teammate_day3’s deep link first.
The output
Onboarding Email Funnel (30d) — graded by ACTION, not click
TEMPLATE SENT OPEN CTR ACTION ACTION-RATE
welcome_day0 4,200 70% 40% 1,080 92% ★ excellent
create_first_project_day1 4,180 50% 20% 209 50% ok
invite_teammate_day3 4,100 50% 30% 41 6.7% ✗ FIX
feature_overview_day5 4,050 40% 10% 162 100% ★ pre-qualified
trial_ending_day12 3,800 70% 30% 380 33% ✗ pricing/friction
KEY INSIGHTS:
invite_teammate_day3 — 615 clicks → 41 invites. Deep link is broken.
Probably routing to workspace home instead of invite modal.
feature_overview_day5 — 10% CTR is fine; 100% action rate means the CTA
self-selects. Don't optimize for opens.
trial_ending_day12 — Click-to-paid conversion is only 33%. Friction at
checkout, not in the email. Investigate separately.
Setting it up
You need email events flowing in from your ESP, with distinct_id matching the in-app one (= user email). Most ESPs (Customer.io, Loops, Resend, Postmark, Sendgrid) ship webhooks — pipe those into a tiny handler that re-emits as Agentry analytics events.
// Webhook handler — e.g. Customer.io or Resend
app.post("/webhooks/email", async (req) => {
const evt = req.body;
// evt.event = "sent" | "opened" | "clicked"
await fetch(`https://api.agentry.sh/v1/analytics/${process.env.AGENTRY_PROJECT_ID}/`, {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.AGENTRY_DSN}`,
"Content-Type": "application/json",
"User-Agent": "myapp-email-relay/1.0", // REQUIRED — Cloudflare 403s default UAs
},
body: JSON.stringify({
event: `email_${evt.event}`, // → email_sent, email_opened, email_clicked
distinct_id: evt.recipient, // ← MUST match in-app distinct_id (= email)
properties: {
email_template: evt.template_name,
utm_campaign: evt.template_name, // mirror for HogQL convenience
link: evt.link_url, // for clicked events
},
timestamp: evt.timestamp,
}),
});
});
For in-app target_action events, you’re presumably already capturing first_project_created, team_member_invited, etc. for signup-funnel. The recipe just joins both sides on distinct_id within the time window.
Variations
- “Same funnel but only for trial users on the Enterprise pricing path.”
- “Compare onboarding email performance across two ESPs — we A/B’d Customer.io vs Loops last quarter.”
- “For the worst-performing template, draft 3 subject-line / CTA variants based on what the winning ones do.”
- “For each clicker who DIDN’T do the target action within 24h, send a follow-up. List them.”