A milestone-based re-engagement journey that splits on persona (technical vs. non-technical) and drives every dormant student builder toward one north-star milestone: their first AI inference.
Users enter from a dynamic List, get classified into a persona lane, and climb the same 5-milestone ladder with persona-tailored copy. Milestone M3 — First Inference is the keystone. Always-on Exit Rules and a 7-email cap apply across the whole journey.
email ends_with .edu AND country = US AND no dashboard_opened in 90dpersona and entry_segment (account_setup / worker_deployed)CS / engineering / IT — peer-builder & portfolio framing
Business / founders / design — no-CLI, ship-fast framing
Users flow top-down from a single Start, hit the persona split, then run down one of two parallel lanes. Each lane is the same tile structure — Email → Time delay → Email — with delays set to skip ahead the moment the milestone event fires. M3 (first inference) is the keystone.
env.AI.run("@cf/meta/llama-3-8b-instruct", { prompt }) returning a result. It's the journey's north-star milestone (per Priyanshi's direction), tracked via the inference_run event, which lets the delay tiles skip ahead and counts as the primary conversion goal.
Everything below maps directly to the Iterable Studio component model so the team can build it tile-by-tile.
.edu + country = US + dormant = true (no login in 90d).persona; unknown → non-technical lane.persona, increment emails_sent, set milestone flags.emails_sent = 7 (5 milestones + ≤2 nudges).Same 5-rung ladder, persona-tailored copy. The keystone row (M3) is highlighted.
| Milestone | Advance event | Technical lane | Non-technical lane |
|---|---|---|---|
| M1 Return to Dash |
dashboard_opened | "See what students like you are building with AI" Peer Workers AI build + template. CTA: Open Workers & Pages · Start a template. |
"Build anything, fast — no terminal required" Describe-your-idea via Build. CTA: Open dashboard · Start a template. |
| M2 First deploy |
worker_deployed | "Deploy it and drop the link in your portfolio" GitHub push or wrangler deploy. CTA: Open Dash · Build. |
"Get it live" Build publishes a real, shareable URL. CTA: Open Dash · Build. |
| M3 ★ First Inference |
inference_run | "Run your first AI model on the edge — free" Llama/Mistral/Whisper, 10K neurons/day. CTA: Fork an AI template. |
"Add AI to your app in a few clicks" Add a chatbot/AI feature via template, no ML setup. CTA: Add AI. |
| M4 Adjacent product |
product_added | "Now put a gateway in front of your AI" AI Gateway: caching = savings + traffic dashboard. |
"Make it more than a demo" D1: store real signups → prove demand. |
| M5 Share |
build_shared | "Ship it loud" X / dev Twitter, GitHub README badge, Discord. UTM share link. |
"Take it further" LinkedIn / X + Cloudflare for Students. UTM share link. |
Five milestones × two personas. Subject + preheader shown for each; {{firstName}} and {{featured_build_title}} are Iterable merge fields. Keystone milestone (M3) is the first-inference moment.
Hi {{firstName | default:"there"}},
You spun up Cloudflare a while back — then midterms, life, whatever. Good news: your account is still here, exactly where you left it.
Here's what another student just shipped on Workers AI: {{featured_build_title}} — {{featured_build_one_liner}}. Built on the free tier, deployed to the global edge in minutes.
Want to start your next one? Open a template with Workers AI already wired up — no boilerplate, no config.
Hi {{firstName | default:"there"}},
Got an idea for a startup, a waitlist page, or a project you want to pitch? You don't need to be an engineer to ship it.
With Build, you describe the site or app you want, start from a template, and Cloudflare handles the deploy — no command line, no setup, no "wait, what's a terminal."
Your dashboard's right where you left it. Pick up where you stopped.
A project that's deployed beats a project that's "almost done."
Push straight from your GitHub repo, or run wrangler deploy on a template — either way you get a live URL you can put in your portfolio, your résumé, or a recruiter DM. Shipped work gets noticed.
Free tier covers it: 100K requests/day on Workers.
The hardest part of building is shipping — let's get yours live.
Tell Build what you want to publish and it'll deploy your site or app for you. You'll get a real URL you can text to a friend, drop into a pitch deck, or post to collect your first signups.
Nothing to install. The free tier covers your launch.
Here's the fun part: add real AI to your build without standing up any infrastructure.
With Workers AI you can run inference on popular open models — Llama, Mistral, Whisper — right at the edge, with a free daily allocation (10K neurons/day). No GPUs, no model hosting, just an API call from your Worker.
Fork an AI starter and make your first inference call in a few minutes.
Want your product to feel smart? Add AI without hiring an engineer.
Start from an AI template and your app can answer questions, summarize text, or chat with users — powered by Workers AI on Cloudflare's network. No models to host, no GPUs, free to try.
It's the feature that makes a demo feel like a real product.
You're calling a model — now make it cheaper and observable.
Route your AI calls (Workers AI, OpenAI, or Anthropic) through AI Gateway and instantly get caching, rate limiting, retries, and a dashboard of requests, tokens, and cost. Cache repeated prompts and you'll see the savings immediately — handy on a student budget.
One endpoint. Still free.
A landing page is a demo. A landing page that captures real signups is traction.
Add D1, Cloudflare's free database, and your project can actually remember things — emails, signups, submissions. The moment real data lands in your database is the moment your idea stops being a demo and starts proving demand.
5 GB free. No separate vendor.
You built it, deployed it, added AI to it. Now let people see it.
Post your build on X, add a "Powered by Cloudflare" badge to your GitHub README, or drop it in the Discord "show your build" channel. It's social proof, a portfolio entry, and the start of your next opportunity.
You shipped something real. Two ways to grow it:
Share it — post your build on LinkedIn or X. Proof you shipped is proof to investors, teammates, and your future self.
Keep building — Cloudflare for Students keeps you in the ecosystem with resources and credits as your project grows.
Every rung uses the same pattern: send → wait 4 days listening for the milestone event → advance on event (skip the wait) or send 1 nudge + 3 days → advance anyway, until a milestone completes, the cap is hit, or an exit rule fires.
Sends on entry.
Sooner if dashboard_opened fires.
1× nudge, then +3 days.
Keystone. Sooner if worker_deployed fires.
On inference_run or window expiry.
On product_added or window expiry → exit.
One event — inference_run — does two jobs: it measures conversion and it triggers the next email. It originates in the Cloudflare product, gets pushed into Iterable, and the delay tile listens for it.
Student makes their first Workers AI call (env.AI.run(...)). Usage is recorded in product data.
BI / Amplitude watches for the account's first inference and dedupes (so only #1 counts).
Amplitude / BIFire the inference_run event + set first_inference_at on the profile.
The M3 delay tile sees the event and routes the user to M4 immediately (skips the nudge).
A single Track API call stamps the event on the user. createdAt lets Iterable order it; dataFields are optional context.
Iterable evaluates branch/exit criteria continuously, so the event pulls the user forward in near-real-time — no waiting out the full delay.
first_inference_at IS null so repeat inferences don't re-fire.Pull dormant .edu contacts from BI → enrich against ZoomInfo → classify technical vs. non-technical via keyword matching on job title, department, and field of study. Result is written to the persona profile field and drives the split at entry.
Counts from the proof-of-concept enrichment run 25_062926_PERSON_*.csv (25 contacts classified). Fields used: Job Title, Department, Persona, Classification_Reason.
unknown. Caveat: ZoomInfo coverage on current students is thin, so expect a sizable unknown bucket — worth A/B testing the unknown→non-technical default.Iterable does not enrich or classify anyone. It only reads data fields on each user's profile. Persona is computed upstream (warehouse + ZoomInfo + the keyword classifier), written onto the Iterable profile as a field, and the Filter tile simply routes on that field. Same for entry segment, which comes from product data.
Outside Iterable — runs before the daily list sync
Dormant .edu accounts (email + product signals: account created, Workers deployed, last login).
Internal Data MCPMatch each email to job title, department, and field-of-study signals.
ZoomInfo exportScore titles/majors against keyword lists → assign persona + entry_segment.
Write fields onto each profile via CSV import, Users API, or reverse-ETL (Hightouch/Census).
/api/users/bulkUpdateInside Iterable — at journey runtime
Dynamic list = .edu + country=US + dormant=true. Users already carry persona & entry_segment.
Criteria: persona = technical → Technical lane. Else → Non-technical lane (unknown defaults here).
Criteria: entry_segment = worker_deployed → skip M2, jump to keystone (M3).
One call per user (or batched via bulkUpdate). The dataFields are what the Filter tiles read.
No code — you pick the field and value in the tile's criteria builder. It evaluates the stored profile field; it does not call ZoomInfo.
persona is already on the profile when the user reaches the Filter tile. Iterable can't enrich mid-journey — it only reads what's there. (A Journey Webhook could call an external API live, but batch enrichment upstream is the right pattern here.)