At Farecompare.com, you can setup fare alerts, like “tell me if airfare for ATL to NYC drops by 20%.” Farecompare will check 3 times a day, and then instantly alert you if they detect the changes you’re looking for. They’re the first to offer such a service, and it’s extremely cool.
They use MailChimp’s API and our powerful dynamic merge tags to send these highly customized “transactional” emails.
Here’s what one of their email alerts looks like:
Now let’s take a look at how they use MailChimp’s dynamic merge tags to get this done…
The challenging thing about these transactional emails is that each recipient might have up to 5 different “city pair” alerts setup. Here’s an example where I have three alerts for three city pairs:
I specified three cities I travel to often (in my fantasy land, where I actually have time to travel). Sydney, Portland, and Boston.
I’ve set them up to send me an email alert whenever airfare to any of these cities changes by 20%:
So you might think, “easy enough. just setup the mailchimp database so that each recipient has merge fields, like fname, lname, origcity1, destcity1, price1, origcity2, destcity2, price2, and so on and so forth.”
Problem is, if one of the city pairs got updated pricing (let’s say ATL-BOS airfare dropped 25%) but the other city pairs didn’t change, the email would need to ONLY list the ATL-BOS information, and NOT the other two city pairs. Basically, you want some conditional statements that say, “If an update for a city pair exists, include it. Otherwise, leave it blank.”
Dynamic content merge tags
Here’s how they do it.
This is what their email looks like in the MailChimp campaign builder:
You’ll notice 5 different “blocks” of content, where a possible city-pair alert would appear.
They’ve coded each of those blocks with our dynamic merge tags like this:
*|IF:ORIG1|*
<table width=”358″ border=”0″ cellspacing=”0″ cellpadding=”0″ bgcolor=”#ffffff” style=”font-family: Arial, Helvetica, sans-serif;font-size: 12px;color: #000000;”>
<tr>
<td colspan=”2″ height=”10″><img src=”http://www.farecompare.com/blah.jpg” alt=”"></td>
</tr>
<tr>
<td width=”197″ valign=”top” style=”padding-left: 10px; padding-top: 10px”>
<strong>Itinerary</strong><br><br>
» From: *|ORIG1|*<br>
» To: *|DEST1|*<br>
</td>
<td width=”161″ align=”center”>
Find fares from<br>
<span style=”font-size: 23px; color: #ff9900″><a href=”http://www.farecompare.com/blah?key=*|KEY1|*“>
<strong>*|PRICE1|*</strong></a></span><br>
*|SAVE1|*<br>
<a href=”http://www.farecompare.com/blah?key=*|KEY1|*“><img src=”http://www.farecompare.com/blah.jpg” alt=”Find Flights” border=”0″></a>
</td>
</tr>
<tr>
<td colspan=”2″ height=”10″><img src=”http://www.farecompare.com/blah.jpg” alt=”"></td>
</tr>
</table>
<br>
*|END:IF|*
There’s a lot of formatting code in there, so let’s distill it down to the important merge tags:
From: *|ORIG1|*
To: *|DEST1|*
Find fares from
*|PRICE1|*
*|SAVE1|*
*|END:IF|*
*|IF:ORIG2|*
From: *|ORIG2|*
To: *|DEST2|*
Find fares from
*|PRICE2|*
*|SAVE2|*
*|END:IF|*
*|IF:ORIG3|*
From: *|ORIG3|*
To: *|DEST3|*
Find fares from
*|PRICE3|*
*|SAVE3|*
*|END:IF|*
So for each block, they say IF there is a price update, then insert it along with its price and savings amount.
If there are no updates, the other blocks will not show up.
This conditional logic is exactly what our dynamic merge tags are for. You can also use conditional merge tags in your A/B test campaigns to swap out and A/B test your email’s content and designs (here’s a tutorial on how to do that).
For a complete list of MailChimp merge tags (and what they all do), see our merge tag cheatsheet.
Refresh Database via API
But remember how they send these updates 3 times a day?
That means they have to wipe everything in MailChimp clean 3 times a day, then re-populate the list with new data for each member.
If you’ve ever created a list in MailChimp, you know that’s no easy task.
Unless you’re using the MailChimp API to sync your member info.
3 times a day, Farecompare connects to MailChimp and performs a member update to refresh all their fields and replace them with the most up-to-the-minute airfares.
Turn off click tracking and use Google Analytics
There’s one important thing to note here. This is a really, really smart hack of MailChimp. Since it’s a hack, there are some compromises. For one, click tracking is not going to be very useful to you if you’re constantly wiping out your database through the API and then replacing all your recipient merge fields. There are more hacks to get around that issue, but we strongly recommend you simply turn off all click tracking, and use our Google Analytics integration instead to track your clicks:
In this type of daily transactional campaign, looking at your campaign stats every day in MailChimp is a little unrealistic anyway. You should just log in to Google Analytics to see how your daily alerts are driving traffic to your website and resulting in conversions.
Who’s this for?
If you run an e-commerce site and you send transactional alerts of some sort (price or inventory alerts, for example), and:
- you want to measure opens, clicks, and conversions,
- AND the alerts will all follow the same standard template
then setting up this kind of MailChimp campaign is perfect. You will need to have someone on staff who can work with the MailChimp API. Or, you can contact a programmer in the MailChimp Experts directory.




Whew. My brain hurts from writing this article.
Very interesting case study, thanks for sharing! Especially because we are looking for a similar solution for a new project but have not been able to find an ESP who is able to do just that.
What if a subscriber does not have any price change and all his fields are empty: how do they prevent sending out an email with all blocks empty? Or do they just flush the whole subscriber DB before they send a new campaign and then import only the subscribers who have updates? Or is there an additional filter they use, like send only to those with at least one price update field not empty?
Maybe I just should check it out myself :-) Can I test the API with a free plan?
@Steve – They “flush” the dB just like you say, AND if the subscriber’s fields are empty, then the conditional merge tags will not display them. Scroll down the article to where I mention “mergetag cheatsheet.”
The MailChimp API is always free.
Ben, thanks for your answer. I’m gonna sign up later for the free plan to play with the API. It would be so great if we could avoid coding all this email sending stuff and just let the chimp do it :)
> if the subscriber’s fields are empty, then the conditional merge tags will not display them
OK, I just thought, if all blocks were empty (i.e. no “updated price” subscriber field at all) then the subscriber would get an email with just the “frame” (header, sidebar, footer) but no content. But now it’s clear: when they only import subscribers with changes, there will always be at least one block with an updated price.
Thanks again – you’re doing a great job with the blog and Mailchimp in general!
@Steve – yep, you said it better than me.
Continuing with Steve’s query, the article doesn’t mention how any emails actually get sent.
Is the missing step to automatically create and send a campaign using the API three times a day?
Wiping “everything in MailChimp clean 3 times a day,” followed by re-populating the list and updating merge tags for everyone doesn’t sound that simple (though a batch update method would probably be nice).
That suggests they have to query listMembers, which sounds like a potentially onerous download, then sort through all that info and send it straight back to MailChimp using one or more listBatchUnsubscribe calls, then do a huge number of individual listSubscribe calls (rather than listUpdateMember as mentioned).
@Christopher – re: how many emails get sent, I’m not sure farecompare would want me to say. But it’s a pretty huge list. I’m not sure about the API-related questions you asked, but I bet you a MailChimp nerd will reply soon. They seem to watch my discussions really, really closely whenever I blog about hacks and APIs and “programming stuff.”
Hi Ben,
I was wondering how the emails actually get sent, not how *many* get sent.. :)
It just seemed like the missing piece of the post.
Thanks for the update.
They include a field in the profile for “Send Alert” and then update this for each send. If this is set to “no” the email address won’t be included in the send.
They are using listBatchSubscribe with the API which will update the profile fields for all existing list members.
My understanding is that they wait for a success message on the profile update through the API and then automatically trigger the campaign send.
very interesting. We want to create a mail system for our 30 day free eval users. They get an email on day 1, 15, 25 and day 45 of their free eval unless they purchase. can you see this being done with Mail Chimp?
@Lary – This will be possible with our upcoming “autoresponder/drip” campaign functionality in v4.1, due in late March.
@Christopher their members are updated like Neil says. Then I believe they are using a combination of campaignReplicate() to make a copy of a previous campaign, campaignUpdate() to change the subject, content, etc, and then campaignSendNow() to actually fire off the campaign.
The alternative approach is to use our psuedo-transactional emails – they are convenient for resending the same campaign over and over with out having to create new ones), but they are not exactly well suited for resending to the same addresses multiple times.
Bonzer. Thanks!
And is It possible to send a custom welcome email to people I just include to one list via API? as soon as I include this person?
I think that autoresponder has an important technical delay of one day…
Thanks in advance.
@Alejandro – Welcome emails are a normal part of the signup process that you can customize. No need to setup an autoresponder for them.
Thanks you Jesse, but… is it possible that my clients receive the welcome message WITHOUT double opt-in?
I mean if I subscribe their by myself?
Thanks
Ah, I should have put two and two together since this is on the transactional blog entry!
Welcome emails are only sent as part of the double opt-in process, so no. If you don’t want to wait on an autoresponder, then you could use transactional emails for that welcome email. All you’d need to do is do a campaignSendNow() call after you subscribe them. Some customers make that call immediately, some just have a job kick it off every 10 minutes or so.
hi,
A few questions/comments
# is there a limit to the field stored in member profile i.e is it possible to store entire email content ( including html ) in a given field ? is there a length limit ? Rather than have a system on our end which does partial logic and stores data in one way and then, replicate the data in another way and have some business logic on mailchimp’s side, thinking is that it’ s almost better to construct entire email on our end. hence when a member update is done, simply put the content of the transactional & personalized email in one field on mailchimp’s end. do let me know if i should be thinking of this some other way.
# would love to know about plans to make this a non-hack.
There is a 255 character limit per field so it would not be possible to post the entire campaign payload into an individual field.
@ Neil. thanks. Would love to know if there are plans to make it a non-hack. As i mentioned, right now, it seems like work is being duplicated when trying to personalize an email i.e data as well as logic is executed on our end as well as on mailchimp’s end. what would be nice is if all logic and data was stored on our end and mailchimp had an easy way to send content/email generated on our end per user. let me know if my request needs clarification.
Sign me up for the Ben fan club :)