Email Templates
Create, manage, and customize email templates with advanced templating engines and dynamic content capabilities.
Email Templates
Create beautiful, responsive email templates with advanced templating engines, conditional logic, and dynamic content. Build reusable templates that adapt to different users, contexts, and campaigns.
Template Creation
Create and manage email templates with the OMX template system:
import { OMXClient } from '@omx-sdk/email';
const omx = new OMXClient({
clientId: 'your_client_id',
secretKey: 'your_secret_key'
});
// Create a new template
const template = await omx.email.templates.create({
name: 'welcome_email',
subject: 'Welcome to {{appName}}, {{firstName}}!',
// HTML content with Handlebars templating
html: `
<!DOCTYPE html>
<html>
<head>
<title>Welcome Email</title>
<style>
.container { max-width: 600px; margin: 0 auto; font-family: Arial, sans-serif; }
.header { background: #4F46E5; color: white; padding: 20px; text-align: center; }
.content { padding: 30px 20px; }
.button { display: inline-block; background: #4F46E5; color: white; padding: 12px 24px; text-decoration: none; border-radius: 5px; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>Welcome to {{appName}}!</h1>
</div>
<div class="content">
<h2>Hi {{firstName}},</h2>
<p>Thank you for joining {{appName}}! We're excited to have you on board.</p>
{{#if needsActivation}}
<p>To get started, please activate your account:</p>
<p><a href="{{activationLink}}" class="button">Activate Account</a></p>
{{else}}
<p>You're all set! Start exploring:</p>
<p><a href="{{dashboardLink}}" class="button">Go to Dashboard</a></p>
{{/if}}
<p>Best regards,<br>The {{appName}} Team</p>
</div>
</div>
</body>
</html>
`,
// Plain text version
text: `
Welcome to {{appName}}!
Hi {{firstName}},
Thank you for joining {{appName}}! We're excited to have you on board.
{{#if needsActivation}}
To get started, please activate your account: {{activationLink}}
{{else}}
You're all set! Start exploring: {{dashboardLink}}
{{/if}}
Best regards,
The {{appName}} Team
`,
// Template metadata
category: 'transactional',
tags: ['welcome', 'onboarding'],
// Required variables
variables: [
{ name: 'firstName', type: 'string', required: true },
{ name: 'appName', type: 'string', required: true },
{ name: 'needsActivation', type: 'boolean', required: false },
{ name: 'activationLink', type: 'string', required: false },
{ name: 'dashboardLink', type: 'string', required: false }
]
});
console.log('Template created:', template.id);Advanced Templating
Use advanced templating features for dynamic content generation:
// Template with conditional blocks and loops
const newsletterTemplate = await omx.email.templates.create({
name: 'monthly_newsletter',
subject: '{{month}} Newsletter - {{highlightCount}} Updates Inside!',
html: `
<!DOCTYPE html>
<html>
<body>
<div class="newsletter">
<h1>{{month}} Newsletter</h1>
{{#if user.isPremium}}
<div class="premium-section">
<h2>Premium Member Benefits</h2>
<p>Thanks for being a premium member! Here are your exclusive updates:</p>
</div>
{{/if}}
<h2>This Month's Highlights</h2>
{{#each highlights}}
<div class="highlight">
<h3>{{title}}</h3>
<p>{{description}}</p>
{{#if image}}
<img src="{{image}}" alt="{{title}}" />
{{/if}}
<a href="{{link}}">Read More</a>
</div>
{{/each}}
{{#with personalizedContent}}
<h2>Recommended for You</h2>
{{#each recommendations}}
<div class="recommendation">
<h4>{{name}}</h4>
<p>{{reason}}</p>
<span class="score">Match: {{matchScore}}%</span>
</div>
{{/each}}
{{/with}}
{{#compare user.engagementLevel "high"}}
<div class="high-engagement">
<p>We've noticed you're highly engaged! Here are some advanced features:</p>
</div>
{{/compare}}
</div>
</body>
</html>
`
});
// Template with custom helpers
const customTemplate = await omx.email.templates.create({
name: 'order_summary',
subject: 'Order {{orderNumber}} - {{formatCurrency total}}',
html: `
<div class="order-summary">
<h1>Order Confirmation</h1>
<p>Order Date: {{formatDate orderDate "MMMM DD, YYYY"}}</p>
<table>
{{#each items}}
<tr>
<td>{{name}}</td>
<td>Qty: {{quantity}}</td>
<td>{{formatCurrency price}}</td>
</tr>
{{/each}}
<tr class="total">
<td colspan="2">Total:</td>
<td>{{formatCurrency total}}</td>
</tr>
</table>
<p>Estimated Delivery: {{addDays orderDate shippingDays "MMMM DD"}}</p>
{{#if isInternational}}
<p>International shipping to {{shippingAddress.country}}</p>
{{/if}}
</div>
`,
// Register custom helpers
helpers: {
formatCurrency: (amount) => `$${amount.toFixed(2)}`,
formatDate: (date, format) => moment(date).format(format),
addDays: (date, days, format) => moment(date).add(days, 'days').format(format)
}
});Template Inheritance
Create reusable layouts and extend them for specific use cases:
// Base layout template
const baseLayout = await omx.email.templates.create({
name: 'base_layout',
type: 'layout',
html: `
<!DOCTYPE html>
<html>
<head>
<title>{{title}}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
/* Base styles */
body { margin: 0; padding: 0; font-family: Arial, sans-serif; }
.container { max-width: 600px; margin: 0 auto; }
.header { background: var(--brand-color, #4F46E5); color: white; padding: 20px; }
.content { padding: 30px 20px; }
.footer { background: #f8f9fa; padding: 20px; text-align: center; font-size: 12px; }
{{#block styles}}{{/block}}
</style>
</head>
<body>
<div class="container">
<div class="header">
<img src="{{logoUrl}}" alt="{{companyName}}" height="40">
{{#block header}}
<h1>{{title}}</h1>
{{/block}}
</div>
<div class="content">
{{#block content}}
<p>Default content</p>
{{/block}}
</div>
<div class="footer">
{{#block footer}}
<p>© {{currentYear}} {{companyName}}. All rights reserved.</p>
<p><a href="{{unsubscribeUrl}}">Unsubscribe</a> | <a href="{{preferencesUrl}}">Update Preferences</a></p>
{{/block}}
</div>
</div>
</body>
</html>
`
});
// Child template extending base layout
const promotionalTemplate = await omx.email.templates.create({
name: 'promotional_email',
extends: 'base_layout',
html: `
{{#extend "base_layout"}}
{{#block styles}}
.promo-banner { background: linear-gradient(45deg, #ff6b6b, #4ecdc4); padding: 15px; text-align: center; color: white; font-weight: bold; }
.product-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin: 20px 0; }
.product-card { border: 1px solid #ddd; border-radius: 8px; padding: 15px; text-align: center; }
.discount-badge { background: #ff4757; color: white; padding: 5px 10px; border-radius: 20px; font-size: 12px; }
{{/block}}
{{#block header}}
<h1>{{promotionTitle}}</h1>
<p>Limited Time Offer!</p>
{{/block}}
{{#block content}}
<div class="promo-banner">
{{discountPercentage}}% OFF - Use code: {{promoCode}}
</div>
<h2>Featured Products</h2>
<div class="product-grid">
{{#each featuredProducts}}
<div class="product-card">
<img src="{{image}}" alt="{{name}}" style="max-width: 100%; height: 150px; object-fit: cover;">
<h3>{{name}}</h3>
<p>{{description}}</p>
<div>
<span class="discount-badge">{{../discountPercentage}}% OFF</span>
<span style="text-decoration: line-through;">${{originalPrice}}</span>
<strong>${{salePrice}}</strong>
</div>
<a href="{{productUrl}}" style="display: inline-block; background: #4F46E5; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px; margin-top: 10px;">Shop Now</a>
</div>
{{/each}}
</div>
<p>Offer expires: {{formatDate expirationDate "MMMM DD, YYYY"}}</p>
{{/block}}
{{/extend}}
`
});Template Components
Build reusable template components for consistent email design:
// Create reusable components
const buttonComponent = await omx.email.templates.createComponent({
name: 'cta_button',
html: `
<a href="{{url}}"
style="display: inline-block;
background: {{color}};
color: {{textColor}};
padding: {{padding}};
text-decoration: none;
border-radius: {{borderRadius}};
font-weight: bold;
{{#if fullWidth}}width: 100%; text-align: center;{{/if}}">
{{text}}
</a>
`,
// Default props
defaultProps: {
color: '#4F46E5',
textColor: 'white',
padding: '12px 24px',
borderRadius: '5px',
fullWidth: false
},
// Required props
requiredProps: ['url', 'text']
});
const productCardComponent = await omx.email.templates.createComponent({
name: 'product_card',
html: `
<div style="border: 1px solid #ddd; border-radius: 8px; padding: 15px; text-align: center; margin-bottom: 20px;">
{{#if image}}
<img src="{{image}}" alt="{{name}}" style="max-width: 100%; height: 150px; object-fit: cover; border-radius: 4px;">
{{/if}}
<h3 style="margin: 15px 0 10px 0; color: #333;">{{name}}</h3>
{{#if description}}
<p style="color: #666; font-size: 14px; margin: 10px 0;">{{description}}</p>
{{/if}}
<div style="margin: 15px 0;">
{{#if originalPrice}}
<span style="text-decoration: line-through; color: #999; margin-right: 10px;">${{originalPrice}}</span>
{{/if}}
<strong style="color: #4F46E5; font-size: 18px;">${{price}}</strong>
</div>
{{> cta_button url=productUrl text="View Product" }}
</div>
`
});
// Use components in templates
const productShowcaseTemplate = await omx.email.templates.create({
name: 'product_showcase',
subject: 'New arrivals just for you!',
html: `
<div style="max-width: 600px; margin: 0 auto; font-family: Arial, sans-serif;">
<h1>New Arrivals</h1>
<p>Check out our latest products, handpicked for you:</p>
{{#each products}}
{{> product_card
name=name
description=description
image=image
price=price
originalPrice=originalPrice
productUrl=url }}
{{/each}}
<div style="text-align: center; margin-top: 30px;">
{{> cta_button
url="https://yourstore.com/products"
text="View All Products"
fullWidth=true }}
</div>
</div>
`
});Template Testing and Preview
Test your templates with sample data and preview across different devices:
// Preview template with sample data
const preview = await omx.email.templates.preview('welcome_email', {
firstName: 'John',
appName: 'YourApp',
needsActivation: true,
activationLink: 'https://yourapp.com/activate/sample',
logoUrl: 'https://yourapp.com/logo.png',
companyName: 'Your Company'
});
console.log('Preview URLs:', {
desktop: preview.desktopUrl,
mobile: preview.mobileUrl,
tablet: preview.tabletUrl
});
// Test template rendering
const testData = {
user: {
firstName: 'Jane',
lastName: 'Doe',
email: 'jane@example.com',
isPremium: true,
tier: 'gold'
},
order: {
number: 'ORD-12345',
total: 129.99,
items: [
{ name: 'Product A', quantity: 2, price: 49.99 },
{ name: 'Product B', quantity: 1, price: 29.99 }
]
}
};
const rendered = await omx.email.templates.render('order_confirmation', testData);
console.log('Rendered HTML:', rendered.html);
console.log('Rendered Text:', rendered.text);
console.log('Rendered Subject:', rendered.subject);
// Validate template syntax
const validation = await omx.email.templates.validate('newsletter_template');
if (!validation.valid) {
console.error('Template validation errors:', validation.errors);
}
// A/B test templates
const abTest = await omx.email.templates.createABTest({
name: 'Welcome Email Test',
variants: [
{
name: 'Version A',
templateId: 'welcome_email_a',
trafficPercentage: 50
},
{
name: 'Version B',
templateId: 'welcome_email_b',
trafficPercentage: 50
}
],
metrics: ['open_rate', 'click_rate', 'conversion_rate'],
duration: '7d'
});Dynamic Content and Personalization
Create templates with advanced personalization and dynamic content blocks:
// Template with dynamic content blocks
const dynamicTemplate = await omx.email.templates.create({
name: 'personalized_newsletter',
subject: 'Your personalized update is here!',
html: `
<div class="newsletter">
<h1>Hello {{firstName}}!</h1>
{{#contentBlock "weather_update"}}
<div class="weather-section">
<h2>Weather in {{location}}</h2>
<p>Today: {{temperature}}°F, {{conditions}}</p>
</div>
{{/contentBlock}}
{{#contentBlock "personalized_recommendations"}}
<h2>Recommended for You</h2>
{{#each recommendations}}
<div class="recommendation">
<h3>{{title}}</h3>
<p>{{description}}</p>
<span class="match-score">{{matchScore}}% match</span>
</div>
{{/each}}
{{/contentBlock}}
{{#contentBlock "local_events" if=location}}
<h2>Events Near You</h2>
{{#each localEvents}}
<div class="event">
<h4>{{name}}</h4>
<p>{{formatDate date "MMM DD"}} at {{venue}}</p>
</div>
{{/each}}
{{/contentBlock}}
</div>
`,
// Content block generators
contentBlocks: {
weather_update: async (user) => {
const weather = await getWeatherData(user.location);
return {
location: user.location,
temperature: weather.temperature,
conditions: weather.description
};
},
personalized_recommendations: async (user) => {
return {
recommendations: await getPersonalizedRecommendations(user.id)
};
},
local_events: async (user) => {
if (!user.location) return null;
return {
localEvents: await getLocalEvents(user.location, user.interests)
};
}
}
});
// Send email with dynamic content
const emailWithDynamicContent = await omx.email.send({
to: 'user@example.com',
template: 'personalized_newsletter',
// Static data
data: {
firstName: 'John',
location: 'New York, NY'
},
// Dynamic content will be generated at send time
generateDynamicContent: true
});Template Management
Manage template versions, backups, and deployment across environments:
// List all templates
const templates = await omx.email.templates.list({
category: 'transactional',
tags: ['welcome'],
limit: 50
});
// Get template details
const template = await omx.email.templates.get('welcome_email');
console.log(template);
// Update template
const updatedTemplate = await omx.email.templates.update('welcome_email', {
subject: 'Welcome to {{appName}}, {{firstName}}! 🎉',
// Version control
version: '2.0',
changelog: 'Added emoji to subject line, improved mobile responsiveness'
});
// Create template version
const newVersion = await omx.email.templates.createVersion('welcome_email', {
html: updatedHtmlContent,
version: '2.1',
changelog: 'Fixed button alignment on Outlook'
});
// Rollback to previous version
await omx.email.templates.rollback('welcome_email', '1.0');
// Clone template
const clonedTemplate = await omx.email.templates.clone('welcome_email', {
name: 'welcome_email_variant',
modifications: {
subject: 'Welcome aboard, {{firstName}}!',
category: 'experimental'
}
});
// Archive unused template
await omx.email.templates.archive('old_template');
// Delete template (permanent)
await omx.email.templates.delete('unused_template', {
confirm: true
});
// Backup templates
const backup = await omx.email.templates.backup({
templates: ['welcome_email', 'newsletter'],
includeVersions: true,
format: 'json'
});
// Restore from backup
await omx.email.templates.restore(backup.id, {
overwriteExisting: false
});Template Optimization
Optimize templates for deliverability, performance, and engagement:
// Analyze template performance
const analysis = await omx.email.templates.analyze('newsletter_template', {
timeRange: '30d',
metrics: ['deliverability', 'engagement', 'rendering']
});
console.log(analysis);
// {
// deliverability: { score: 85, issues: ['Missing alt text for images'] },
// engagement: { openRate: 0.24, clickRate: 0.06, unsubscribeRate: 0.002 },
// rendering: {
// clientSupport: { outlook: 'good', gmail: 'excellent', apple: 'good' },
// issues: ['Table layout may break on small screens']
// }
// }
// Get optimization suggestions
const suggestions = await omx.email.templates.getOptimizationSuggestions('newsletter_template');
console.log(suggestions);
// [
// {
// type: 'accessibility',
// priority: 'high',
// suggestion: 'Add alt text to all images for better accessibility',
// impact: 'Improves deliverability and accessibility'
// },
// {
// type: 'mobile',
// priority: 'medium',
// suggestion: 'Use responsive design patterns for better mobile experience',
// impact: 'Increases mobile engagement by ~15%'
// }
// ]
// Optimize template automatically
const optimized = await omx.email.templates.optimize('newsletter_template', {
areas: ['accessibility', 'mobile', 'deliverability'],
// Optimization options
options: {
addAltText: true,
optimizeImages: true,
minifyHtml: true,
improveContrast: true,
addDarkModeSupport: true
}
});
// Test template across email clients
const clientTest = await omx.email.templates.testClients('welcome_email', {
clients: ['gmail', 'outlook_2019', 'apple_mail', 'yahoo'],
devices: ['desktop', 'mobile'],
generateScreenshots: true
});
console.log('Client test results:', clientTest.results);
console.log('Screenshots:', clientTest.screenshots);Best Practices
- Responsive Design: Ensure templates work across all devices and email clients
- Accessibility: Include alt text, proper contrast, and semantic HTML
- Performance: Optimize images and minimize HTML/CSS size
- Testing: Test templates across major email clients before deployment
- Version Control: Maintain template versions and changelog
- Personalization: Use data to create relevant, personalized content