- Use casesOnboardingWelcome flows that branch on what new users actually do.Trial conversionUsage-driven nudges that stop the moment they pay.Win-backSpot who's gone quiet and bring them back.CommunityRead Discord activity off the same contact as your product.Failed paymentsReminders that sound human and stop when payment clears.Paid acquisitionSend Meta the sale, not the click — values, real click IDs.CampaignsOne-off broadcasts to a list — scheduled, cancelable.Fire and forgetBuilt for agents — domain to first send in half an hour.
- RecipesOnboardingWelcome series, activation milestones, waitlists.Trial & billingTrial arcs, dunning, and upgrade nudges.E-commerceCarts, orders, deliveries, and restocks.RetentionWin-backs, NPS, digests, anniversaries.SchedulingLand sends at the right local time.Human-in-the-loopApprovals, lead alerts, concierge touches.Agents & AIAgents on the same event stream your app uses.PipelinesWebhook sources in, destinations out.
- PlaybookActivationTurn signups into users who felt the value.OnboardingGet new users to the habit, not just the tour.RetentionCatch the drop before it becomes churn.Revenue & expansionPlays that move paid conversion and expansion.WinbackRe-open the conversation with the lapsed.Referral & growth loopsLet the product's users source the next users.DeliverabilityLand in the inbox before you optimize anything else.Measurement & attributionProve the system moved the metric.
- Templates
- Services
- Pricing
- Docs
- Articles
- Changelog
Superpowers for growth engineers.
Hogsend is a TypeScript framework for growth teams that code. Identify and enrich the people on your product, react to their events, message them where they are, and measure what moved.
$ pnpm dlx create-hogsend@latestEvent plugins
Code-first
Journeys are TypeScript in your repo. Version, review and ship them like the rest of your product.
Full-funnel
Onboarding, activation, retention, monetization — one engine across every stage.
Event-powered
React to any event from PostHog, your product, your warehouse or any webhook source.
Measure impact
Built-in experiments, holdouts and lift measurement on every journey.
Whenlifecyclelivesinyourcodebase,everyleakisfixable.When lifecycle lives in your codebase, every leak is fixable.
Hogsend turns each leak into a response your product can ship. Built for code-first teams that need a best-in-class growth engine.
Send, wait, branch on what they did
waitForEvent parks the journey durably until THIS user creates a project — or three days pass. The branch afterwards is an if statement, and the stalled path tags the growth team on Discord.
Using Hogsend means that lifecycle marketing becomes part of the product, not a campaign bolted on beside it.
Journeys as code
Lifecycle logic is TypeScript in your repo, reviewed, type-checked, and versioned like the rest of your product.
Your provider, your reputation
Sends go through your own Resend or Postmark account, or any provider behind the EmailProvider contract.
Durable execution
Journeys run as Hatchet durable tasks. A seven-day wait survives deploys, restarts, and crashes.
Measure everything. React in TypeScript. Prove what moved revenue. Steer it all from Studio. Review and ship marketing like the rest of your product, watched live as every send, wait, and branch runs.
Put your growth machine on autopilot.
Your coding agent works where your lifecycle does: inside your codebase. Ask for an outcome and it can write, modify, and validate the journey without another drag-and-drop builder.
Plain TypeScript surface
Journeys are defineJourney() files. Claude Code, Cursor, or any agent writes and modifies them like any other code.
export const onboarding = defineJourney({
trigger: { event: "user.signed_up" },
run: async (user, ctx) => { … },
});
Validated by your type-checker
No drag-and-drop canvas to drift out of date — the compiler rejects a journey that references a template that doesn't exist.
# pre-push
$ pnpm check-types
✓ journeys/welcome.ts
✓ journeys/winback.ts — 0 errors
A CLI agents can drive
hogsend skills plus --json on every command give agents a first-class interface to inspect and operate the running system.
$ hogsend journeys --json
[ { "id": "onboarding", "status": "registered" } … ]
Journey Blueprints
Agents author journeys as JSON — stored in your database, enrolling users without a deploy. Review and enable them in Studio. When one earns permanence, hogsend blueprints promote turns it into a code journey in your repo.
MCP server
npx @hogsend/mcp connects Claude Desktop, Cursor, or claude.ai to your running instance. Create blueprints, run health reports, send test emails — your admin key, your infrastructure.
LLMs write and modify journeys like any other code in your repo
The journeys every product should run — shipped by default.
Welcome / onboarding. Greet people the moment they sign up, then branch on whether they've actually tried anything yet.
Activation nudge. Drive the one action most correlated with sticking around — before the trial clock runs out.
Feature adoption. Most churn is a feature users never found. Surface the one they're missing.
Trials that convert. Match the ask to how much they've really used, not the day on the calendar.
Payment saves. Involuntary churn is the biggest leak you can plug. Remind, and stop the moment it clears.
Win-backs. You already paid to acquire them once — winning them back costs a fraction of a new signup.
Milestones. Celebrate progress and reinforce the habit at the moments value actually lands.
Referrals. Ask for the referral at the moment value lands, when they're most likely to say yes.
Every journey here sends one of 13 React Email templates in the scaffold → · copy-paste variants for all of these live in the 35-recipe cookbook →
Start with one command. pnpm dlx create-hogsend@latest . Everything below ships with it, in v0.59.0.
Run the scaffolder yourself: pnpm dlx create-hogsend@latest .
Every video becomes an event stream. This player is @hogsend/video. Press play — the feed beside it is the events it captures.
Elena Verna, Head of Growth at Lovable, on Lenny's Podcast. Played through our own @hogsend/video; press play and the real watch-depth events replace the loop. All our React components →
@hogsend/videostandbyWatch-depth events from the player, streaming live.
Depth that survives scrubbing
percentWatched is the deepest point reached — monotonic, so skipping back and forth never inflates it.
Milestones fire once
video.progress lands a single event at 25, 50, 75, and 90 percent, alongside started, completed, and replay.
One event shape, any player
YouTube, Vimeo, and native <video> emit the same events, so journeys never care where the video lives.
Emitters, not lock-in
createHogsendEmitter feeds your journeys; the same interface writes to PostHog or GA4, or all of them combined.
Watch depth is a journey trigger like any other event — the retargeting play in the playbook runs on it.
Read the video docs →Customize the whole journey with feature flags. Flip any part of your marketing on or off, anytime.
Native, DB-backed flags, evaluated against your Hogsend contacts by the same targeting engine that runs your journeys. One flag can swap a headline, a video, an email, or a whole branch of a journey. Flip the arms below and the page reacts, running on the real API on the right.
Lifecycle without the hire
Onboarding, trials, and win-back ship as code your agents extend, with no lifecycle team to staff.
visitor-teammultivariateOne arm per visitor. Your targeting rules choose it in production; flip the arms here to preview.
import { useFlag } from "@hogsend/react";
export function Hero() {
// One flag decides who's reading. Sticky per visitor, no redeploy.
const team = useFlag("visitor-team");
return <TeamHero team={team} />; // swaps the video + the pitch
}evaluated for you
One definition, read everywhere. The same evaluation runs in the browser, on the server, and inside a journey. Already run PostHog flags? Keep them and read them right beside these.
Read the flags docs →Bill, Derek, and Bob all work at Acme. Hogsend can treat them as one account.
Contact groups roll individual activity up to the company, team, or workspace it belongs to. One call associates a contact with a group; every event they fire carries the association, membership accrues automatically, and the account reads back as one entity in Studio.
Acme Inc
proCompany · acme.com · ID: grp_8f4a72e9vs last 30 days
vs last 30 days
32 days
Excellent
6 pts
Usage & Health
Activity (events)
Last 30 daysProperties
Tags
Members (3)
| Member | Events (30d) | Last seen | Role | ||
|---|---|---|---|---|---|
Bill Chen | bill@acme.com | 1,24018% | 2h ago | admin | |
Derek Vaughn | derek@acme.com | 4306% | 1d ago | member | |
Bob Portis | bob@acme.com | 2104% | 3d ago | member |
acme.comcompanyOne (type, key) is the account. The browser associates events; the server writes properties and members.
// server — the secret key writes properties
await hogsend.groups.identify({
groupType: "company",
groupKey: "acme.com",
displayName: "Acme Inc",
properties: { plan: "pro", seats: 42 },
});
await hogsend.groups.addMember({
groupType: "company",
groupKey: "acme.com",
contactId: bill.id,
role: "admin",
});secret — writes properties
Group properties and memberships are secret-key writes, enforced at the route.
Journeys are person-scoped today — group-level journeys are a later phase, not a fine-print surprise.
Read the 0.50 write-up →The email answers back. Send surveys, questions and buttons in your email.
Every link in every email is rewritten to your own domain at send time, so opens and clicks are tracked first-party — no provider pixels. An EmailAction goes further: the click emits a named event with properties, and a waiting journey reads the answer directly.
to: founder@acme.dev
subject: Quick check-in on your trial
Hey — you're a week into the trial. One click tells us where you are, straight from this email:
Each button is an EmailAction — a link whose click emits trial.check_in with its answer. First click wins.
trial-check-inwaitingSent through the tracked mailer: every link rewritten to your domain, opens and clicks first-party.
- email.senttrial-check-in
- links rewritten/v1/t/c/9f2c…
- open pixel/v1/t/o/58d1…
- ctx.waitForEventtrial.check_in · 3d
the journey hears
Tracked Links & QR Codes. Mint a link, get a QR code, put it on anything.
Every managed link gets a vanity slug, first-party click tracking, and a print-ready SVG or PNG QR code from the API. Scans count separately from clicks, a personal link identifies the scanner, and because the QR encodes a durable engine URL you can re-point a printed code any time.
spring-mailertracked linkMinted with one call, hs.links.create() or the Studio Links view. SVG and PNG QR straight from the API.
One code on 5,000 postcards. A public link never carries a person — scans count separately from web clicks, so the mailer reports like a channel.
1,204
qr scans
310
web clicks
9.8%
scan rate
on scan
Direct mail, conference badges, packaging — anything you can print becomes a journey trigger.
Read the direct-mail play →Your Discord is a lifecycle channel, too. Connect a Discord account to a user on your app.
The bot verifies through their inbox — a one-click emailed confirm, never the Discord-reported address. From then on messages and reactions keep a last-seen on the contact, and a journey can send a DM the same way it sends an email, gated on the member’s channel preference.
jamie11:12 AM
/link
discord-connectlive flowOne slash command folds a Discord account onto the contact — verified through their inbox, never the Discord-reported email.
contact
emailjamie@northwind.io
discord_id—
isDiscordLinked—
last_seen—
on the wire
Built for community-led companies — the channel your users actually read, wired into the same journeys as email and SMS.
Read the Discord docs →Every journey change is an experiment. So prove it moved the number.
Ship two versions of a journey to a randomised split, hold back a control, and Hogsend measures the goal event against it. You get the incrementality — the welcome series raised activation, and by how much — not a guess.
activation-welcomelive testEvery version ran against a holdout. Select one to read the lift it measured on the goal event.
primary goal
activation
+22%
activation lift vs holdout
96%
confidence
8,412
enrolled users
14 days
experiment window
readout · v3
Illustrative readout — the report Hogsend generates from your own journeys and goals.
Version the journey
Every edit is a version. Run the new one against the last — no separate tool.
Split with a holdout
A randomised share gets the change; a control gets nothing to measure against.
Read the lift
The goal event, measured against the control, with a confidence you can act on.
Know which edit moved the number
You reworked the welcome series three weeks ago — did it work? Every enrollment carries a fingerprint of the journey code that created it, so the readout splits before-vs-after on its own. No tagging, no spreadsheet archaeology.
meta.versionSplit-test without an experiment platform
One call inside the journey assigns each user an arm — sticky across retries and redeploys, no assignment service to run. The readout reports every arm against the same control.
ctx.variantProof, not attribution flattery
Opens and clicks can't tell you what would have happened anyway. Hold back 10% as a control and the lift is measured against people who got nothing — the only number allowed to say "caused".
meta.holdoutIt won't let you fool yourself
A +40% on twelve users is noise. Under 10 conversions the verdict stays "collecting" — never a percentage; small cohorts ship flagged. You act when the number can carry the decision.
smallSampleAttributed, influenced, and incremental stay separate numbers — only the holdout-backed one may say "caused". Already live? hogsend attribution backfill credits your whole history.
People do more than click emails. Payments, sign-ups, support threads, SMS replies — and more to come.
There’s one plugin system behind all of these — webhook presets in the engine, @hogsend/plugin-* packages beside it, built in the open in the same repo. Signals land as first-class events that trigger, branch, or exit a journey; the CRM and ads legs carry conversions back out.
Every preset is defineWebhookSource() under the hood — a source we don’t ship is a transform function away.
See all integrations →We use Hogsend to power hogsend.com.
Sign up below. Our own Hogsend install sends the welcome email and powers the feed, bell, survey, and branching that follows.
This isn’t a mock — it’s our own install, a stock create-hogsend app in production. The welcome email arrives from hello@hogsend.com in seconds; the feed, bell, and survey card are real @hogsend/react components. See the full set →
Why not just use PostHog Workflows? Sometimes you should.
Workflows is genuinely good. It lives in the PostHog UI your team already has open, consumes the events you already capture, and needs nothing deployed. And it isn't either/or — both run off the same PostHog events. Hogsend amplifies everything PostHog does.
Zero extra infrastructure. A tab in the PostHog UI your team already has open, consuming the events you already capture — nothing to deploy, nothing to operate.
Multi-channel out of the box. Email, SMS, push, Slack, and webhooks without writing a line.
Non-engineers can ship. The no-code canvas means whoever owns lifecycle can see and edit the flow — no developer in the loop.
A genuinely generous free tier. Light volume fits inside it; after that it's per-send pricing on top of your PostHog bill.
The flow is code you own. Versioned completely — git log knows who changed the discount email and why. PR review, tests, and rollback apply like everywhere else.
Your domain, your reputation. Sends go through your own Resend or Postmark account, not a managed sender.
Past the canvas ceiling. Park until this user acts, send in their timezone, trigger journeys from journeys, cap re-entries — control flow boxes and arrows can't express.
Integrate any service. A journey is an async TypeScript function — call any API you can import, or an LLM mid-run, and branch on the answer.
They scratch different itches. If you want a drag-and-drop editor, Workflows has you covered — you're here because you'd rather build marketing in, as a developer or a product-first engineering team. If you're a PostHog team, or about to become one, use each where it fits.
Read the full comparisonDurable execution, by Hatchet.
Every journey runs on Hatchet, the durable execution engine underneath Hogsend. It's what lets a long ctx.sleep survive a deploy and resume two days later exactly where it left off. Hogsend builds on Hatchet rather than rolling its own durability.
Survives deploys & restarts
A long ctx.sleep keeps running across a deploy and resumes days later, exactly where it left off.
Automatic retries & timeouts
Failed steps retry and waits expire on their own — durability you don't have to hand-roll.
Self-host it, or use Hatchet Cloud
Run Hatchet-Lite next to your app, or point at Hatchet Cloud. Same engine either way.
What it costs. Contact count appears in neither bill.
There is no paid tier. You pay for hosting — the Railway template provisions Postgres, Redis, Hatchet, the API, and the worker — and for your own Resend or Postmark account.
*Published pricing, checked July 2026.
Find what you need.
Is Hogsend open source?
Hogsend is source-available under the Elastic License 2.0 (ELv2). You can read, modify, and self-host all of it for free; the only restriction is offering Hogsend itself as a managed service.
What does Hogsend cost?
The software is free — there is no paid tier. You self-host and pay only your own infrastructure plus your Resend or Postmark account. No per-contact, per-profile, or per-send fees.
How is Hogsend different from PostHog Workflows?
Workflows is PostHog's built-in no-code canvas with a managed sender. Hogsend is typed TypeScript in your repo with durable waits, behavioral branching, and your own email provider — for when lifecycle logic outgrows boxes and arrows.
Does Hogsend replace Resend or use it?
It uses it. Hogsend is the orchestration layer — journeys, segments, suppression, tracking — and sends through your own Resend account by default, with Postmark as a one-env-var swap. Resend's own Automations cover simple dashboard-built sequences; Hogsend is for when the logic belongs in your repo — event-triggered, type-checked, and portable across providers.
Do I need PostHog to use Hogsend?
No. Send first-party events directly with @hogsend/js or the Data API, use signed webhook presets for Stripe, Clerk, Supabase, or Segment, or define any custom source. PostHog is a first-class optional integration.
Will my emails survive a deploy mid-journey?
Yes. Journeys run as Hatchet durable tasks: a user three days into a seven-day wait keeps waiting through deploys, restarts, and crashes, and resumes exactly where they were.
Can AI agents write Hogsend journeys?
Yes — journeys are plain TypeScript files, so coding agents can read your product events and types, write or modify a journey, and leave you a reviewable diff. Your type-checker validates it before it ships.
First send in minutes.
One prompt scaffolds the app, Docker, env, and ten journeys — the welcome series included. Your agent reads the docs and does the rest.
❯Visit hogsend.com/docs and implement lifecycle marketing for our product — start with the welcome series.
Paste into your coding agent
