Helpdocs for email services
When utilising email services to communicate with your audience, it's essential to follow the warm-up process diligently. Warm-up is a strategic method to gradually increase your email sending volume, ensuring a smooth and successful delivery to your recipients.
Why is Warm-Up Necessary?
Sending a large number of emails abruptly, without a proper warm-up, can trigger spam filters on recipient clients such as Gmail or Outlook. These email providers monitor the sending behavior of IP addresses and domains. If they detect a sudden and high volume of emails, they may categorize your emails as spam or may blacklist your domain, leading to potential delivery issues.
How to Conduct Warm-Up:
To optimize your email deliverability, we recommend starting with a conservative email volume and gradually increasing it over a specified period. Here's a suggested approach:
Warm up process email cycle
Day 1 – Send to 500
➡️ Start slow. Only target users who recently engaged with your services (opened/clicked).
Goal: Build trust with mailbox providers.
Day 2 – Send to 1,000
➡️ Double your volume, but monitor bounce and complaint rates.
Goal: Prove your list is clean and responsive.
Day 3 – Send to 2,000
➡️ Increase only if performance from Day 1–2 was strong.
Goal: Avoid hitting spam traps.
Day 4 – Send to 3,000
➡️ Continue increasing, but ensure your open rate stays above 10%.
Goal: Keep engagement steady.
Day 5 – Send to 5,000
➡️ Still prioritize recent or active users.
Goal: Avoid sudden dips in performance.
Day 6 – Send to 7,000
➡️ Do not send to cold or new contacts yet.
Goal: Maintain consistency.
Day 7 – Send to 10,000
➡️ Look beyond just delivery rates - check how many emails were delivered vs failed.
Goal: Ensure real visibility.
Day 8 – Send to 12,000
➡️ Clean your list, remove any hard bounces or invalid emails.
Goal: Prevent damage to sender score.
Day 9 – Send to 14,000
➡️ Spam complaints should stay below 0.1%.
Goal: Show mailbox providers your emails are wanted.
Day 10 – Send to 15,000
➡️ You can slowly reintroduce older contacts if engagement is solid.
Goal: Test cautiously.
Day 11 – Send to 12,000
➡️ Slight pullback for better deliverability
Goal: Let your reputation recover.
Day 12 – Send to 8,000
➡️ Let mailbox providers stabilize your sending behavior.
Goal: Build long-term trust.
Day 13 – Send to 6,000
➡️ Don’t spike volumes. Stay consistent with the warm-up curve.
Goal: Avoid filters and throttling.
Day 14 – Send to 5,500
➡️ Review performance. Decide whether to scale up or pause.
Goal: Plan for the next phase of your email strategy.
The dip in volume on Day 12–14 in a warm-up plan is a strategic cooldown, and here's Why We Reduce Volume Around Day 12
Avoid Triggering Spam Filters - If you keep increasing volume non-stop for 14 days, mailbox providers may flag it as "suspicious behavior" — especially from a new domain. A sudden drop, pause, or dip simulates more natural human activity (e.g. campaign cycles, weekends, or a controlled test).
Let the IP and Domain Reputation Stabilize - After 80K emails, mailbox providers need time to analyze your metrics: spam complaints, bounce rates, opens, click-throughs, unsubscribes.The dip acts like a “buffer period” for that analysis to settle in.
Prevent Overheating the IP Reputation - If any minor complaints or bounces start creeping in during high-volume days, continuing to increase can burn the domain/IP reputation. Pulling back early lets you course-correct.
Most legitimate senders don’t send more and more every single day. A healthy pattern looks like: increase → cooldown → new batch later.
If you keep increasing to the end without pause, ESPs may think:
You're a bulk sender spamming aggressively
You're not following best practices
Your domain could be linked to spam traps
You're faking trust to reach more inboxes fast
Once you complete the warm-up cycle, you can switch to sending in campaigns (not bulk blasts), and include delays, frequency and A/B Testing to keep performance high.
Gradual Increase (Even After Warm-Up) - Start with 20K–30K emails per day for a couple of days and then increase gradually.Day
1-2: 20K
Day 3-4: 40K
Day 5-6: 50K
Day 7: 75K
Day 8 onwards: 100K if everything looks good (engagement rates, inbox placement).
Best Approach:
Week 1 Post-Warm-Up: Slowly scale from 20K–50K per day.
Week 2–4 Post-Warm-Up: Gradually push up to 100K per day, but monitor metrics and scale cautiously.
Ongoing: Continue optimizing your email list, monitor engagement, and review metrics to ensure that you’re staying within best practices.
Benefits of Warm-Up:
Improved Deliverability: Gradual increases in email volume help establish a positive sending reputation of your domain and IP, reducing the likelihood of emails being marked as spam.
Enhanced Engagement: ISPs (Internet Service Providers) are more likely to recognize your emails as legitimate, leading to improved open and click-through rates.
Avoiding Spam Folders: Warm-up minimizes the risk of your emails ending up in the spam folder, ensuring they reach your audience's primary inbox.
Key Takeaway:
Taking the time to perform an effective warm-up is an investment in the success of your email delivery. By following this process, you maximize the chances of your emails being delivered to the intended recipients' inboxes.
Warm Up in Email Sending
May 20, 2025The Complete Guide to Smarter Emailing
Email Solution remains one of the most powerful and cost-effective tools to reach your audience directly. This master article covers everything you need to know—from strategy basics to advanced techniques including AI content generation
What’s New with Our Email Platform (2025 Update)
Here’s a quick look at the most impactful updates that can transform how you send emails:
✍️ AI Content Generator: Create Emails in Seconds
Struggling with content? Use our AI Content Generator to write subject lines, promotional messages, newsletters, and more — instantly. Just give a prompt, and AI takes care of the rest.
🤖 Intellisend AI: Smarter Email Scaling
Want to reach more users without extra effort? Intellisend AI automatically sends AI-generated messages to the rest of your audience after your set limit is reached — perfect for large-scale campaigns.
🧩 Handlebars Templates: Dynamic Personalization
Make every email feel 1:1. Insert user names, product details, or behavior-based triggers with Handlebars, no coding needed.
✨ Gmail Markup: Stand Out in the Inbox
Use Gmail Markup to display interactive buttons, ratings, and offers directly inside the Gmail preview — improving open and click-through rates.
Why Email Solution Still Matters in 2025
Direct & Personal: Email connects you directly with your audience in a private space.
High ROI: Email consistently delivers one of the highest returns on investment compared to other channels.
Automation & AI Ready: Modern platforms let you automate, personalize, and scale your campaigns efficiently.
Measurable: Track opens, clicks, conversions, and optimize using real-time data.
Leveraging AI Content Generation for Smarter Emails
AI-powered content generation is revolutionizing email marketing by helping you:
Create personalized, relevant email at scale.
Generate subject lines, body text, and CTAs tailored to different segments instantly.Save time and reduce manual effort.
AI tools help draft multiple versions, enabling faster campaign launches.Optimize and test messaging.
Use AI suggestions to refine tone, increase engagement, and run A/B tests.
At MSG91, our AI Content Generator helps you craft compelling emails faster while maintaining your brand voice and relevance.
Best Practices & Strategies to Boost Performance
Use concise, engaging subject lines with personalization.
Optimize send times based on audience behavior.
Test different frequencies to balance engagement and unsubscribes.
Focus on mobile-friendly email designs.
Clean and segment your list frequently.
Leverage AI-generated content for speed and personalization.
📢 Email Still Works: The Channel That Outperforms
In a world full of noise, email keeps winning. Here’s why 5 Proven Strategies to Boost Your Email Open Rates & Conversions
Email's Master Article
Jun 3, 2025This feature is used to connect your existing email service provider (Gmail & Outlook) to your MSG91 account and use the same to send emails.
How to set up email connections?
1. Click on Email on the home screen

2. Click on connections from the left menu pane.

3.You’ll get the option to choose from Gmail or Outlook. Choose one of the following option which you want to use and click continue (You’ll be redirected to the service provider URL for login)

4. Provide the login credentials of your existing email or create a new account and click continue

5. It’ll take you to the page where you can check the permissions for MSG91 and also the privacy policy, if you are ok with that click on continue. Once done you can see the account under Connection in your email dashboard and you will be able to send emails from it.

Note : The email limits and restrictions will be as per your email service provider.
6. If you want to add another account you can click on the Connect button on the top left side of the screen and continue from step 3 to step 5

7. If you want to delete the any existing connection then just hover over the connection that you want to delete and click the delete button
8. In order to send emails using API for connections, kindly use the same cURL as Send Email API and replace "domain" with "integration_id" which can be found under the connection tab. Also "from field" is not required if you are using connections as the from email will be the email as per connection.

Email Connections
Nov 9, 2024Now you can easily view and reply to all email responses from a single dashboard. Explore Hello Inbox to efficiently manage all replies and respond promptly. To get started, simply click on Hello.

After clicking on Hello, select All Inboxes

After clicking on all inboxes, Then, simply click on the Create Inbox button located at the top-right corner

After clicking on create inbox, Select Email Inbox to integrate your Msg91 email account

Select MSG91 and click on Create Now

After selecting the MSG91 Inbox, you’ll need to fill in the following required fields:
Inbox Name: This is how the inbox will be displayed in Hello, allowing you to view all responses. Select Domain: Choose the configured domain you have used in your MSG91 email service.
Email : Add the same email ID you used for sending emails through your MSG91 account.
From Name: Set the name that will appear to users when responses are triggered
After filling in the required fields, click on Next to proceed.

In the next field, set the permissions for handling email responses. Select the agent or team based on your Hello Inbox configuration, or click on 'Invite an Agent' or 'Add a Team' as needed. Once done, click on Save & Next to proceed

Next, you'll see the forwarding option. Keep the settings as they are and click Next

In the next field, you'll find the configuration option. Add your signature so it appears in the email replies. Enable Show Mail Thread to view the entire email thread in Hello. The Undo Email option allows you to undo an email after sending, set the duration and click Save.

After clicking on Save, your integrated Email Inbox will appear in the "Hello All Inboxes" section and below the filters, your configured Email Inbox will be displayed. After selecting the Email Inbox, you can review all received email responses and respond accordingly.

Next, to complete the setup, go back to your MSG91 email service, click on Webhook, and add the provided URL - https://api.phone91.com/receive-mail/ in the Incoming Email Post section & click save to start receiving email responses in Hello.

By following these simple steps, you can seamlessly manage and respond to all your email replies instantly from a single dashboard using the same email ID in Hello.
You can also check how to use Hello to manage and reply to all your customer responses effectively - https://video-faq.viasocket.com/demo/cm4s55g6y01uqql5jashah58w
How to View and Respond to All Email Replies in One Dashboard with Hello Inbox
Feb 4, 2025Gmail Markup enhances your emails by allowing recipients to take quick actions directly from their Gmail inbox. With this feature, users can interact with emails - such as checking into a flight, confirming an event, or tracking an order - without opening the email fully or clicking external links.
Example Use Case:
For an event reservation email, Gmail Markup can display an "Add to Calendar" button to allow users to add the event to their calendar, and a "Directions" button to get directions to the event directly from their inbox.

Testing Gmail Markup
If you want to test before whitelisting your email ID, follow these simple steps:
Visit script.google.com
After visiting, select 'New Project' from the left side.
You will see a file named Code.gs on the left side.
Replace the content of Code.gs with the following code.
/** * Send an email with schemas in order to test email markup. */ function testSchemas() { try { const htmlBody = HtmlService.createHtmlOutputFromFile('mail_template').getContent(); MailApp.sendEmail({ to: Session.getActiveUser().getEmail(), subject: 'Test Email markup - ' + new Date(), htmlBody: htmlBody }); } catch (err) { console.log(err.message); } }
Click on Save
Next, click on the left top side Files (+) icon, select HTML, and name the file mail_template to match the parameter used in the JavaScript above.
Replace the content of HTML with the following code & Click on Save
<!-- Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <html> <head> <script type="application/ld+json"> { "@context": "http://schema.org", "@type": "FlightReservation", "reservationNumber": "RXJ34P", "reservationStatus": "http://schema.org/Confirmed", "underName": { "@type": "Person", "name": "Eva Green" }, "reservationFor": { "@type": "Flight", "flightNumber": "110", "airline": { "@type": "Airline", "name": "United", "iataCode": "UA" }, "departureAirport": { "@type": "Airport", "name": "San Francisco Airport", "iataCode": "SFO" }, "departureTime": "2027-03-04T20:15:00-08:00", "arrivalAirport": { "@type": "Airport", "name": "John F. Kennedy International Airport", "iataCode": "JFK" }, "arrivalTime": "2027-03-05T06:30:00-05:00" } } </script>
To test the script:
Select the tab for Code.gs
Make sure the function testSchemas is selected in the Select function dropdown menu.
Click Run in the Apps Script development environment.To test the script:
The first time you run the script, you'll be asked to grant authorization.
Once you grant the authorization and the script runs successfully, check your inbox for an email sent from yourself — similar to the following screenshot:

If you're planning to use Gmail interactive cards or actions in your email templates, you must go through Google's schema whitelisting process. This guide will walk you through everything in detail,
How to Apply for Gmail Schema Whitelisting (Step-by-Step Guide)
Before starting:
You should have access to your production domain email (like
[email protected]
)You must have a ready-to-use HTML email template
Step 1: Create the HTML Email Template on MSG91
Log in to your MSG91 Dashboard
Go to Email > Template
Create a new HTML email template using the HTML & Text editor.
Design the email body you want your customer to receive.
Step 2: Choose the Interactive Card (Schema Type)
Google supports a variety of interactive cards, such as:
Flight check-ins
Order tracking
Event confirmations
Appointment reminders
Parcel deliveries
Restaurant or hotel reservations
To see all supported cards and examples: Visit: Gmail Markup Documentation
Note - You can pass multiple parameters as per Gmail Markup documentation. However, what appears in the Gmail preview popup is decided by Google.
Step 3: Add Schema Markup to Your HTML Email
Once you’ve choosed the interactive card:
Select the card on the Gmail Markup Documentation
Copy the JSON-LD schema code (starts with
<script type="application/ld+json">
)In your Msg91 HTML Email, paste this code after the
<head>
tag.
Tip: Make sure to:
Replace all
sample values
in the schema with your actual data or Handlebars variables “{{var}}”Do not remove the “provider” section – it’s mandatory
Step 4: Validate Your Schema Code
Use Google’s Email Markup Tester to confirm everything is correct.
Go to Email Markup Tester
Paste the entire HTML email code
Replace variables with real sample data
Click Validate
If it shows “No errors detected,” you’re good to go.
Step 5: Test Your Email Schema via Google Apps Script
You can also test how your schema looks in a real Gmail inbox.
Click New Project
You will see a file named
Code.gs
. Replace its content with the following:
/**
* Send an email with schemas in order to test email markup.
*/
function testSchemas() {
try {
const htmlBody = HtmlService.createHtmlOutputFromFile('mail_template').getContent();
MailApp.sendEmail({
to: Session.getActiveUser().getEmail(),
subject: 'Test Email markup - ' + new Date(),
htmlBody: htmlBody
});
} catch (err) {
console.log(err.message);
}
}
Click Save.
Click the
+
icon → Choose HTML → Name the file asmail_template
.Paste the validated email template in this HTML file.
Click Save.
Go back to
Code.gs
→ Select functiontestSchemas
→ Click Run.

After successful execution, you'll receive the interactive markup email in the Gmail inbox of the account you used to log in to App Script. Please check only that email ID. If everything appears correctly, proceed to Step 6
Step 6: Send Schema Email from MSG91 to Google
Now as your email template is tested and validated, it’s time to send the real email to Google for whitelisting.
Open your email template in MSG91.
Before sending, make sure:
You are using your actual production email address (e.g.,
[email protected]
).The schema (JSON-LD code) is correctly placed after the
<head>
tag in the HTML template.All dynamic variables are properly mapped in the HTML code.
The email you send should be the final version that your customers will receive.
Submit the email template for approval within MSG91.
This approval usually takes around 30 minutes.Once approved, go to Send Email:
Set the recipient email to:
[email protected]
Select your validated template.
Fill in all variable values with actual data
Ensure the “From” email domain (e.g.,
@yourcompany.com
) matches your business domain or subdomain.
❗ Do not use an email from a generic domain like Gmail or Yahoo.Choose the email address you want to whitelist in the “From” section, making sure it includes your business domain—for example, [email protected].
Send the email directly from MSG91.
Important Notes:
Do not use a testing domain or sandbox email address.
Do not forward this email — it must be sent freshly and directly from MSG91.
Step 7: Submit Google Whitelisting Form (Final Step)
Visit the Gmail Schema Whitelisting Form - Gmail Whitelist Request Form
You’ll be asked for the following:
Important Guidelines
No Promotional Content: Google does not approve schemas for promotional or marketing emails
Use Production Email & Domain
Wait Time: Approval takes between 7 days to 3 weeks
After submitting, Google will manually review and respond to your request. Once approved, your email ID is whitelisted to send interactive schema-based emails via MSG91.
What is Gmail Markup and How to Use It?
Jun 6, 2025
What is Handlebars and How to Use It in MSG91?
Handlebars is a simple, logic-less templating engine that lets you create dynamic email content using expressions inside double curly braces ({{}}
). MSG91 supports Handlebars helpers to help you personalize emails at scale without needing multiple templates.
Supported Conditional Statements in MSG91 Handlebars:
Basic
if
,else
,else if
if
with root contextunless
greaterThan
greaterThan
withelse
lessThan
lessThan
withelse
Equals
Equals with else
notEquals
notEquals with else
And without else
And with else
Basic or
Or with else
Length
Iterations
Examples of Handlebars Helpers with MSG91
Each example includes:
Handlebars Template (logic used)
JSON Sample Data (variables passed)
Resulting HTML Output (what the user sees)
1) Basic If, Else, Else If - (Greet user based on their loyalty tier)
Explain the conditional logic that personalizes the email based on the user’s loyalty tier.
{{#if user.tier.gold}}
<p>Hello Gold Member! Enjoy exclusive offers just for you.</p>
{{else if user.tier.silver}}
<p>Hello Silver Member! Here's something special for your next order.</p>
{{else}}
<p>Hello Shopper! Unlock rewards by joining our loyalty program.</p>
{{/if}}
How it works:
Checks if the user is a Gold member, shows Gold message.
Else if Silver, shows Silver message.
Otherwise, shows a default message for all others.
JSON – Sample Data You’ll Pass
Show example JSON data where variables match what the template expects.
{
"recipients": [
{
"to": [
{ "name": "test", "email": "[email protected]" }
],
"variables": {
"user": {
"tier": {
"gold": true,
"silver": false
}
}
}
},
{
"to": [
{ "name": "test2", "email": "[email protected]" }
],
"variables": {
"user": {
"tier": {
"gold": false,
"silver": true
}
}
}
},
{
"to": [
{ "name": "test3", "email": "[email protected]" }
],
"variables": {
"user": {
"tier": {
"gold": false,
"silver": false
}
}
}
}
],
"from": {
"name": "Test",
"email": "[email protected]"
},
"domain": "testtest.com",
"template_id": "testtemplate"
}
Note:
true
means the tier applies to that user.Only one tier should be
true
per user for correct output.
HTML – Final Output Your Users Will See
Show the rendered email content for each test case:
<!-- Test data 1 -->
<p>Hello Gold Member! Enjoy exclusive offers just for you.</p>
<!-- Test data 2 -->
<p>Hello Silver Member! Here's something special for your next order.</p>
<!-- Test data 3 -->
<p>Hello Shopper! Unlock rewards by joining our loyalty program.</p>
2) If with a root - (Show support contact if user account is suspended)
Handlebars Template (with root and nested variable) handlebars Copy Edit
{{#if user.suspended}}
<p>Warning! Your account is suspended, please call: {{@root.supportPhone}}</p>
{{/if}}
// Test data
{
"user": {
"suspended": true
},
"supportPhone": "1-800-555-5555"
}
<!-- Resulting HTML -->
<p>Warning! Your account is suspended, please call: 1-800-555-5555</p>
3) Unless - (Show reminder message if the user hasn't placed an order)
<!-- Template -->
{{#unless user.hasOrdered}}
<p>You haven't placed an order yet. Use code <strong>WELCOME10</strong> to get 10% off your first purchase!</p>
{{/unless}}
// Test data 1: User has not ordered
{
"user": {
"hasOrdered": false
}
}
// Test data 2: User has ordered
{
"user": {
"hasOrdered": true
}
}
<!-- Resulting HTML -->
<!-- Test data 1 output -->
<p>You haven't placed an order yet. Use code <strong>WELCOME10</strong> to get 10% off your first purchase!</p>
<!-- Test data 2 output -->
<!-- No output shown, since the user has already placed an order -->
4) greaterThan
Basic greaterThan - (Show high-value alert if the user’s balance exceeds a certain amount)
<!-- Template -->
{{#if (greaterThan user.balance 100000)}}
<p>Alert: Your account balance exceeds ₹1,00,000. Consider investing to grow your savings.</p>
{{/if}}
// Test data 1: Balance is more than 100000
{
"user": {
"balance": 125000
}
}
// Test data 2: Balance is less than 100000
{
"user": {
"balance": 45000
}
}
<!-- Resulting HTML from test data one-->
<!-- Test data 1 output -->
<p>Alert: Your account balance exceeds ₹1,00,000. Consider investing to grow your savings.</p>
<!-- Test data 2 output -->
<!-- No output, since balance is below threshold -->
5) greaterThan with else - (Show free shipping if cart value exceeds ₹2000, else suggest how much more to add)
<!-- Template -->
{{#if (greaterThan cart.total 2000)}}
<p>Congrats! You're eligible for <strong>Free Shipping</strong>.</p>
{{else}}
<p>Add items worth ₹{{subtract 2000 cart.total}} more to unlock <strong>Free Shipping</strong>.</p>
{{/if}}
// Test data 1: Cart total > 2000
{
"cart": {
"total": 2300
}
}
// Test data 2: Cart total < 2000
{
"cart": {
"total": 1450
}
}
<!-- Resulting HTML from test data one-->
<!-- Test data 1 output -->
<p>Congrats! You're eligible for <strong>Free Shipping</strong>.</p>
<!-- Test data 2 output -->
<p>Add items worth ₹550 more to unlock <strong>Free Shipping</strong>.</p>
6) lessThan
Basic lessThan - (Show encouragement if the student scored below 50%)
{{#if (lessThan user.score 50)}}
<p>Don't give up! You scored below 50%. Here's a free revision module to help you improve.</p>
{{/if}}
// Test data 1: Score less than 50
{
"user": {
"score": 42
}
}
// Test data 2: Score 50 or above
{
"user": {
"score": 78
}
}
<!-- Resulting HTML from test data one-->
<!-- Test data 1 output -->
<p>Don't give up! You scored below 50%. Here's a free revision module to help you improve.</p>
<!-- Test data 2 output -->
<!-- No output, since the score is not less than 50% -->
7) lessThan with else - (Encourage user if steps are low, celebrate if steps are good)
<!-- Template -->
{{#if (lessThan user.dailySteps 5000)}}
<p>You’ve taken {{user.dailySteps}} steps today. Let’s aim for 5,000! A short walk can make a big difference.</p>
{{else}}
<p>Great job! You've completed {{user.dailySteps}} steps today. Keep up the healthy habit!</p>
{{/if}}
// Test data 1: Less than 5000 steps
{
"user": {
"dailySteps": 3200
}
}
// Test data 2: 5000 steps or more
{
"user": {
"dailySteps": 7200
}
}
<!-- Resulting HTML from test data one-->
<!-- Test data 1 output -->
<p>You’ve taken 3200 steps today. Let’s aim for 5,000! A short walk can make a big difference.</p>
<!-- Test data 2 output -->
<p>Great job! You've completed 7200 steps today. Keep up the healthy habit!</p>
8) Equals -
Basic equals - (Checking if the user has a winning code)
<!-- Template -->
<p>
Hello Ben!
{{#equals customerCode winningCode}}
You have a winning code.
{{/equals}}
Thanks for playing.
</p>
// Test data one
{
"customerCode": 289199,
"winningCode": 289199
}
// Test data two
{
"customerCode": 167320,
"winningCode": 289199
}
<!-- Resulting HTML from test data one-->
<p>Hello Ben! You have a winning code. Thanks for playing.</p>
<!-- Resulting HTML from test data two-->
<p>Hello Ben! Thanks for playing.</p>
9) Equals with else - (Show a winning or non-winning message based on code match)
<!-- Template -->
<p>
Hello Ben!
{{#equals customerCode winningCode}}
You have a winning code.
{{else}}
You do not have a winning code.
{{/equals}}
Thanks for playing.
</p>
// Test data one
{
"customerCode": 289199,
"winningCode": 289199
}
// Test data two
{
"customerCode": 167320,
"winningCode": 289199
}
<!-- Resulting HTML from test data one-->
<p>Hello Ben! You have a winning code. Thanks for playing.</p>
<!-- Resulting HTML from test data two-->
<p>Hello Ben! You do not have a winning code. Thanks for playing.</p>
10) notEquals - (Show a message if the user’s appointment is not today)
<!-- Template -->
<p>
Hello Ben!
{{#notEquals currentDate appointmentDate}}
Your appointment is not today.
{{/notEquals}}
We look forward to your visit.
</p>
// Test data one
{
"currentDate": 20230715,
"appointmentDate": 20230715
}
// Test data two
{
"currentDate": 20230710,
"appointmentDate": 20230715
}
<!-- Resulting HTML from test data one-->
<p>Hello Ben! We look forward to your visit.</p>
<!-- Resulting HTML from test data two-->
<p>Hello Ben! Your appointment is not today. We look forward to your visit.</p>
11) notEquals with else - (Show different messages depending on whether today is the appointment date)
<!-- Template -->
<p>
Hello Ben!
{{#notEquals currentDate appointmentDate}}
Your appointment is not today.
{{else}}
Your appointment is today.
{{/notEquals}}
We look forward to your visit.
</p>
// Test data one
{
"currentDate": 20230715,
"appointmentDate": 20230715
}
// Test data two
{
"currentDate": 20230710,
"appointmentDate": 20230715
}
<!-- Resulting HTML from test data one-->
<p>Hello Ben! Your appointment is today. We look forward to your visit.</p>
<!-- Resulting HTML from test data two-->
<p>Hello Ben! Your appointment is not today. We look forward to your visit.</p>
12) And
And without else - (Show a message only if both favorite food and drink are provided)
<!-- Template -->
<p>
Hello Ben!
{{#and favoriteFood favoriteDrink}}
Thank you for letting us know your dining preferences.
{{/and}}.
We look forward to sending you more delicious recipes.</p>
// Test data one
{
"favoriteFood": "Pasta",
"favoriteDrink": ""
}
// Test data two
{
"favoriteFood": "Pasta",
"favoriteDrink": "Coffee"
}
<!-- Resulting HTML from test data one -->
<p>Hello Ben! We look forward to sending you more delicious recipes.</p>
<!-- Resulting HTML from test data two -->
<p>
Hello Ben! Thank you for letting us know your dining preferences. We look forward
to sending you more delicious recipes.
</p>
13) And with else - Personalizing Follow-Up Based on Input Completion
<!-- Template -->
<p>
Hello Ben!
{{#and favoriteFood favoriteDrink}}
Thank you for letting us know your dining preferences.
{{else}}
If you finish filling out your dining preferences survey, we can deliver you recipes we think you'll be most interested in.
{{/and}}.
We look forward to sending you more delicious recipes.</p>
// Test data one
{
"favoriteFood": "Pasta",
"favoriteDrink": ""
}
// Test data two
{
"favoriteFood": "Pasta",
"favoriteDrink": "Coffee"
}
<!-- Resulting HTML from test data one -->
<p>
Hi Ben! If you finish filling out your dining preferences survey, we can
deliver you recipes we think you'll be most interested in. We look forward to
sending you more delicious recipes.
</p>
<!-- Resulting HTML from test data two -->
<p>
Hi Ben! Thank you for letting us know your dining preferences. We look forward
to sending you more delicious recipes.
</p>
14) Basic or - Suggesting Content Based on Interests
<!-- Template -->
<p>
Hello Ben!
{{#or isRunner isCyclist}}
We think you might enjoy a map of trails in your area.
{{/or}}.
Have a great day.
</p>
// Test data one
{
"isRunner": true,
"isCyclist": false
}
// Test data two
{
"isRunner": false,
"isCyclist": false
}
// Test data three
{
"isRunner": false,
"isCyclist": true
}
<!-- Resulting HTML from test data one -->
<p>
Hi Ben! We think you might enjoy a map of trails in your area. You can find
the map attached to this email. Have a great day.
</p>
<!-- Resulting HTML from test data two -->
<p>Hi Ben! Have a great day.</p>
<!-- Resulting HTML from test data three -->
<p>
Hi Ben! We think you might enjoy a map of trails in your area. You can find
the map attached to this email. Have a great day.
</p>
15) Or with else - Personalizing Based on Known or Unknown Interests
<!-- Template -->
<p>
Hello Ben!
{{#or isRunner isCyclist}}
We think you might enjoy a map of trails in your area. You can find the map attached to this email.
{{else}}
We'd love to know more about the outdoor activities you enjoy. The survey linked below will take only a minute to fill out.
{{/or}}.
Have a great day.
</p>
// Test data one
{
"isRunner": true,
"isCyclist": false
}
// Test data two
{
"isRunner": false,
"isCyclist": false
}
// Test data three
{
"isRunner": false,
"isCyclist": true
}
<!-- Resulting HTML from test data one -->
<p>
Hi Ben! We think you might enjoy a map of trails in your area. You can find
the map attached to this email. Have a great day.
</p>
<!-- Resulting HTML from test data two -->
<p>
Hi Ben! We'd love to know more about the outdoor activities you enjoy. The
survey linked below will take only a minute to fill out. Have a great day.
</p>
<!-- Resulting HTML from test data three -->
<p>
Hi Ben! We think you might enjoy a map of trails in your area. You can find
the map attached to this email. Have a great day.
</p>
16) Length - You want to remind users if they have items left in their cart.
<!-- Templates -->
<p>
Hello Ben!
{{#greaterThan (length cartItems) 0}}
It looks like you still have some items in your shopping cart. Sign back in to continue checking out at any time.
{{else}}
Thanks for browsing our site. We hope you'll come back soon.
{{/greaterThan}}
</p>
Copy code block
// Test data one
{
"cartItems": ["raft", "water bottle", "sleeping bag"]
}
// Test data two
{
"cartItems": []
}
<!-- Resulting HTML with test data one-->
<p>
Hello Ben! It looks like you still have some items in your shopping cart. Sign
back in to continue checking out at any time.
</p>
<!-- Resulting HTML with test data two-->
<p>Hello Ben! Thanks for browsing our site. We hope you'll come back soon.</p>
17) Iterations
You can use the {{#each}}
helper to loop through data, such as lists or arrays, and display each item in your email template.
Basic Iterator with each - You want to show customers a list of their recent orders to remind them of their purchase history.
<!-- Template -->
<ol>
{{#each user.orderHistory}}
<li>You ordered: {{this.item}} on: {{this.date}}</li>
{{/each}}
</ol>
// Test data
{
"user": {
"orderHistory": [
{
"date": "2/1/2025",
"item": "shoes"
},
{
"date": "1/4/2025",
"item": "hat"
}
]
}
}
<!-- Resulting HTML -->
<ol>
<li>You ordered: shoes on: 2/1/2018</li>
<li>You ordered: hat on: 1/42017</li>
</ol>
Combined examples -
The following examples demonstrate how to combine multiple Handlebars helpers to create dynamic, personalized email templates.
1) Dynamic content creation
<!-- Template -->
{{#each user.story}}
{{#if this.male}}
<p>{{this.date}}</p>
{{else if this.female}}
<p>{{this.item}}</p>
{{/if}}
{{/each}}
// Test data
{
"user": {
"story": [
{
"male": true,
"date": "2/1/2018",
"item": "shoes"
},
{
"male": true,
"date": "1/4/2017",
"item": "hat"
},
{
"female": true,
"date": "1/1/2016",
"item": "shirt"
}
]
}
}
<!-- Resulting HTML -->
<p>2/1/2018</p>
<p>1/4/2017</p>
<p>shirt</p>
2) Dynamic content creation with dynamic parts 1
<!-- Template -->
{{#each user.story}}
{{#if this.male}}
{{#if this.date}}
<p>{{this.date}}</p>
{{/if}}
{{#if this.item}}
<p>{{this.item}}</p>
{{/if}}
{{else if this.female}}
{{#if this.date}}
<p>{{this.date}}</p>
{{/if}}
{{#if this.item}}
<p>{{this.item}}</p>
{{/if}}
{{/if}}
{{/each}}
// Test data
{
"user": {
"story": [
{
"male": true,
"date": "2/1/2018",
"item": "shoes"
},
{
"male": true,
"date": "1/4/2017"
},
{
"female": true,
"item": "shirt"
}
]
}
}
<!-- Resulting HTML -->
<p>2/1/2018</p>
<p>shoes</p>
<p>1/4/2017</p>
<p>shirt</p>
3) Dynamic content creation with dynamic parts 2
<!-- Template -->
{{#if people}}
<p>People:</p>
{{#each people}}
<p>{{this.name}}</p>
{{/each}}
{{/if}}
// Test data
{
"people": [{ "name": "Bob" }, { "name": "Sally" }]
}
<!-- Resulting HTML -->
<p>People:</p>
<p>Bob</p>
<p>Sally</p>
Example Use Case: Order Confirmation Email Using Handlebars
Objective:
Send a personalized order confirmation email that dynamically includes the customer’s name and lists all the items they purchased, with quantity and pricing.
User Scenario:
Riya places an order on your eCommerce website. She buys:
1 Black Dress – ₹1,499
2 Lipsticks – ₹299 each
Instead of hardcoding product details or creating different templates for every order, you use Handlebars to dynamically populate the data.
Data Sent to MSG91 (via API or platform)
"first_name": "Riya",
"order_id": "ORD10293",
"order": {
"items": [
{ "name": "Black Dress", "quantity": 1, "price": 1499 },
{ "name": "Lipstick", "quantity": 2, "price": 299 }
]
}
}
Handlebars-Based Email Template
<h2>Hello {{first_name}},</h2>
<p>Thanks for your purchase! Here are your order details:</p>
<h3>Order ID: {{order_id}}</h3>
<table width="100%" cellpadding="10" cellspacing="0" border="1">
<thead>
<tr>
<th>Product</th>
<th>Qty</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{{#each order.items}}
<tr>
<td>{{name}}</td>
<td>{{quantity}}</td>
<td>₹{{price}}</td>
</tr>
{{/each}}
</tbody>
</table>
<p>We hope you enjoy your purchase. </p>
Output Received by Riya
Hello Riya,
Thanks for your purchase! Here are your order details:
Order ID: ORD10293
Product | Qty | Price
-------------------------------
Black Dress | 1 | ₹1499
Lipstick | 2 | ₹299
We hope you enjoy your purchase. Hello Riya,
Benefits of Using Handlebars
Without Handlebars | With Handlebars in MSG91 |
---|---|
You send each order email individually | Use one dynamic template for every order. |
Multiple emails flying everywhere - hard to track issues | Always accurate and personalized using live data. |
Credits wasted sending separate emails for each order | Save credits — one smart email covers everything. |
1. Log in to Your MSG91 Email Account
Open your MSG91 Dashboard.
2. Go to Templates and Click “Create Template”
Navigate to the Email section → Templates → Click Create Template.
3. Choose “Start from Scratch” or Use AI
You can either:
Build a new template from scratch, or
Use “Generate via AI” and then enhance it with Handlebars
4. Insert Handlebars in the Email Body
Use Handlebars directly in your HTML editor to dynamically display personalized content based on the order data.
5. Test Your Template
Click Preview or use sample JSON data to see your template in action. MSG91 will render real-time results based on your test data.
6. Submit for Approval and Launch
Once your template is ready:
Submit for approval.
After approval, use it in your transactional flows or campaigns.
Done! Your personalized template is live.
Why Use It?
Dynamic, personalized emails at scale
Great for order updates, cart recovery, offers, and more
Compatible with automation and transactional flows
Need Help?
If you’re unsure about your data format or template logic, our team is here to assist.
Email: [email protected]
Live Chat: Available on MSG91 Dashboard