Free Welcome Email Template — New Subscriber Onboarding
New subscribers · onboarding · welcome series
Includes:HTML fileHandlebars variablessample-data.jsonVariables reference600px · Inline CSS · No dependencies
This template is compatible with Mailchimp automations, Klaviyo Flows, SendGrid Dynamic Templates, Brevo transactional emails, HubSpot workflows, Postmark, and any backend using Handlebars.js, Jinja2, or Liquid templating.
Template Preview
Previewed with sample-data.json. Replace {{variables}} with your ESP tags before sending.
How to use it
1
Download or copy the HTML
Self-contained file. No external dependencies.
2
Swap variables for your ESP tags
See the reference table below for Mailchimp, SendGrid, Klaviyo.
3
Or plug into a template engine
Handlebars.js · Jinja2 · Liquid. Use sample-data.json to test.
4
Preview before sending
Paste rendered HTML back into MailViewr to verify.
The “What to Expect” bullet list uses a {{#each expectations}} loop. Each item requires one field: this.text (the bullet text). Add, remove, or reword bullets by adjusting the expectations array in your template data.
How to use this template
Step-by-step integration guide for Mailchimp, SendGrid, Klaviyo, Brevo, HubSpot, Handlebars.js, Jinja2, and Liquid.
Download the HTML template — variables are already Handlebars syntax, no changes needed.
In SendGrid: Email API → Dynamic Templates → Create a Dynamic Template.
Add a new version and paste the HTML into the code editor.
In the Test Data panel, paste your JSON data object.
Use the template ID in API calls with the dynamic_template_data field.
⚠ Gotcha
Handlebars support is only available in Dynamic Transactional Templates — not Marketing Campaigns. Make sure you're using the correct template type.
Variable mapping
Template variable
Klaviyo tag
{{first_name}}
{{ first_name }}
{{discount_percent}}
{{ discount_percent }}
{{offer_price}}
{{ offer_price }}
{{expiry_hours}}
{{ expiry_hours }}
{{cta_url}}
{{ cta_url }}
{{terms_url}}
{{ terms_url }}
{{unsubscribe_url}}
{{ unsubscribe_url }}
{{company_name}}
{{ company_name }}
{{year}}
{{ year }}
{{#each features}}
{% for feature in features %}
{{this.name}}, {{this.original_price}}
{{ feature.name }}, {{ feature.original_price }}
{{/each}}
{% endfor %}
Steps
Download the HTML template.
Replace all variables and loops using the mapping table above.
In Klaviyo: Campaigns → Create Campaign → Email → drag in an HTML block.
Paste the modified HTML.
Use Preview with a profile to verify variable substitution.
⚠ Gotcha
Klaviyo uses Jinja2-style syntax, not Handlebars. The {{#each}} loop must be rewritten as {% for feature in features %} … {% endfor %}.
Variable mapping
Template variable
Brevo tag
{{first_name}}
{{ contact.FIRSTNAME }}
{{discount_percent}}
{{ params.discount_percent }}
{{offer_price}}
{{ params.offer_price }}
{{expiry_hours}}
{{ params.expiry_hours }}
{{cta_url}}
{{ params.cta_url }}
{{terms_url}}
{{ params.terms_url }}
{{unsubscribe_url}}
{{ params.unsubscribe_url }}
{{company_name}}
{{ params.company_name }}
{{year}}
{{ params.year }}
{{#each features}}
{% for feature in params.features %}
{{this.name}}, {{this.original_price}}
{{ feature.name }}, {{ feature.original_price }}
{{/each}}
{% endfor %}
Steps
Download the HTML template.
Replace variables using the mapping table above.
In Brevo: Email Campaigns → Template Library → New Template → paste HTML.
Pass transactional params in your API call under the params object.
Preview and test before sending.
⚠ Gotcha
Brevo distinguishes between contact attributes (contact. prefix) and transactional params (params. prefix). Mixing them up is the most common integration error.
Variable mapping
Template variable
HubSpot tag
{{first_name}}
{{ contact.firstname }}
{{unsubscribe_url}}
{{ unsubscribe_link }}
{{company_name}}
{{ account.company_name }}
{{discount_percent}}
{{ discount_percent }}
{{offer_price}}
{{ offer_price }}
{{expiry_hours}}
{{ expiry_hours }}
{{cta_url}}
{{ cta_url }}
{{terms_url}}
{{ terms_url }}
{{year}}
{{ year }}
{{#each features}}
{% for feature in features %}
{{this.name}}, {{this.original_price}}
{{ feature.name }}, {{ feature.original_price }}
{{/each}}
{% endfor %}
Steps
Download the HTML template.
Swap variables to HubL syntax using the mapping table above.
Load and render the template using the snippet below.
from jinja2 import Environment
from datetime import datetime
env = Environment()
with open('template.html') as f:
template = env.from_string(f.read())
html = template.render(
first_name='Alex',
discount_percent='20',
offer_price='$79',
expiry_hours='48',
cta_url='https://example.com/deal',
terms_url='https://example.com/terms',
unsubscribe_url='https://example.com/unsubscribe',
company_name='Acme Inc.',
year=datetime.now().year,
features=[
{'name': 'Feature A', 'original_price': '$99'},
{'name': 'Feature B', 'original_price': '$49'},
],
)
⚠ Gotcha
Jinja2 uses {% %} for logic blocks and {{ }} for variables. The Handlebars {{#each}} loop must be rewritten as {% for feature in features %} … {% endfor %}.
Variable mapping
Template variable
Liquid tag
{{first_name}}
{{ first_name }}
{{discount_percent}}
{{ discount_percent }}
{{offer_price}}
{{ offer_price }}
{{expiry_hours}}
{{ expiry_hours }}
{{cta_url}}
{{ cta_url }}
{{terms_url}}
{{ terms_url }}
{{unsubscribe_url}}
{{ unsubscribe_url }}
{{company_name}}
{{ company_name }}
{{year}}
{{ year }}
{{#each features}}
{% for feature in features %}
{{this.name}}, {{this.original_price}}
{{ feature.name }}, {{ feature.original_price }}
{{/each}}
{% endfor %}
Steps
Download the HTML template.
Replace Handlebars syntax with Liquid using the mapping table above.
In Shopify Emails: use {{ customer.first_name }} for customer-scoped data.
In Klaviyo or generic Liquid contexts: use flat {{ first_name }} syntax.
Preview with a test customer or profile to verify rendering.
⚠ Gotcha
Shopify Liquid uses customer-scoped variables ({{ customer.first_name }}), while standard Liquid uses flat variables ({{ first_name }}). Know which context you're targeting.
Frequently asked questions
Yes. This welcome email template is completely free to download and use. No signup required.
Yes. Replace the {{variable}} placeholders with Mailchimp merge tags. For example, replace {{first_name}} with *|FNAME|* and {{unsubscribe_url}} with *|UNSUB|*.
Yes. Klaviyo uses Liquid syntax. Scalar variables use {{ variable }} with spaces. Replace {{unsubscribe_url}} with {{ unsubscribe_url }} and link it appropriately in your flow.
Yes. The template ships with Handlebars syntax natively, including a {{#each expectations}} loop for the onboarding list. For Jinja2 change {{variable}} to {{ variable }} and {{#each expectations}} to {% for item in expectations %}. A sample-data.json is included to test rendering.
Yes. The template is 600px max-width with fully inline CSS. It renders correctly in Gmail, Outlook, Apple Mail, and mobile clients.
Replace {{company_name}} with your brand name, update the gradient header colours in the inline style attributes, and swap the CTA link {{cta_url}} to your onboarding page.