Segflow lets you write marketing automation flows in pure code. You can define user segments with SQL queries, write campaign logic in TypeScript, and create email templates in React + Tailwind.
// Define your user properties
interface UserAttributes {
email: string;
name: string;
}
const config: SegflowConfig<UserAttributes> = {
// Define user segments with SQL
segments: {
'inactive-users': {
evaluator: (db) => db
.select({ id: schema.users.id })
.from(schema.users)
.innerJoin(schema.events, eq(schema.events.userId, schema.users.id))
.where(eq(schema.events.name, 'login'))
.groupBy(schema.users.id)
.having(sql`MAX(schema.events.createdAt) < NOW() - INTERVAL 30 DAY`)
}
},
// Define campaign logic with TypeScript
campaigns: {
'winback-campaign': {
segments: ['inactive-users'],
behavior: 'dynamic', // Auto-exits when user becomes active again
flow: function* (ctx, rt) {
for (let i = 0; i < 10; i++) {
yield rt.sendEmail('winback');
yield rt.wait({ days: 2 ** i }); // Wait 1, 2, then 4 days
}
}
}
}
};
Define user groups with the full power of SQL:
segments: {
'big-spenders': {
evaluator: (db) => db
.select({ id: schema.users.id })
.from(schema.users)
.innerJoin(schema.events, eq(schema.events.userId, schema.users.id))
.where(eq(schema.events.name, 'purchase'))
.groupBy(schema.users.id)
.having(sql`sum(${schema.events.attributes}->'$.amount') > 1000`)
}
}
Write complex flows with regular TypeScript:
campaigns: {
'onboarding': {
segments: ['new-users'],
behavior: 'static',
flow: function* (ctx, rt) {
yield rt.sendEmail('welcome');
yield rt.wait({ days: 1 });
if (!ctx.user.profileCompleted) {
yield rt.sendEmail('complete-profile-reminder');
yield rt.wait({ days: 3 });
}
yield rt.sendEmail('feature-highlights');
}
}
}
Design emails with familiar tools:
templates: {
'welcome': {
subject: (user) => `Welcome ${user.name}!`,
component: ({ user }) => (
<Html>
<Head />
<Tailwind>
<Body>
<Preview className="text-blue-600">Welcome aboard!</Preview>
<Text className="text-slate-600">Thanks for joining us {user.name}!</Text>
<Button href="https://example.com/get-started">
Get Started
</Button>
</Body>
</Tailwind>
</Html>
)
}
}
Track user activity and trigger emails with a straightforward client:
// Create or update users
await client.createUser('user123', {
email: '[email protected]',
name: 'Jane'
});
// Track login events
await client.emit('user123', 'login');
// Track purchase events
await client.emit('user123', 'purchase', {
orderId: 'ord_123',
amount: 99.99
});
Send immediate, event-triggered emails like password resets and order confirmations:
transactions: {
'password-reset': {
event: 'reset_password_requested',
subject: (user) => `Reset Your Password`,
component: ({ user, event }) => (
<Html>
<Head />
<Tailwind>
<Body>
<Preview>Reset your password</Preview>
<Text className="text-slate-600">Click the link below to reset your password:</Text>
<Button href={event.resetLink}>
Reset Password
</Button>
</Body>
</Tailwind>
</Html>
)
}
}
// Trigger the email immediately when needed
await client.emit('user123', 'reset_password_requested', {
resetLink: 'https://example.com/reset/abc123'
});
Campaigns run in real-time. As soon as a user enters a segment, they start receiving the campaign. For `dynamic` campaigns, users exit immediately when they no longer match the segment criteria.
Segflow tracks each user's progress through campaigns in its database. Users can only be at one step in a campaign at a time.
Segflow uses MySQL to track its own state. Your application can use any database - you just need to send user events to Segflow via its API.
Currently Postmark and Amazon SES. Adding new providers is straightforward through the open-source codebase.
Segflow empowers developers to build sophisticated marketing automation workflows tailored to their unique business needs, all while maintaining full control over their code and data.
Get Started