EmailTimer.App

Countdown timers and personalized images for Iterable email

Your subscribers see how long is left on the offer, counted from the moment they open the message, and it goes into the Iterable campaign you have already built. One snippet, in the merge syntax Iterable already uses.

Animated countdown in the digital style, reading 02 days 03 hours 34 minutes 12 seconds and counting down
A render from the engine at 600 by 200, the size that goes into a Iterable image block.

Iterable merge syntax

The tags you already use, around the image

The same merge fields that put a subscriber's name in your subject line go in the link and the alt text around the image, where Iterable fills them in as it sends. They never go inside the image address, for the reason in the warning further down. A name or a deadline drawn inside the image itself comes from an address signed for each subscriber, held in a contact field.

First name
{{firstName}}
Coupon code
{{couponCode}}
Deadline
{{deadlineTimestamp}}
Email address
{{email}}

Checked against Iterable's own documentation: Personalizing Templates with Handlebars (Iterable Support Center), read on 17 September 2026.

The snippet to paste into Iterable

Put it in iterable drag and drop html block or code template. There are two shapes, and which one you want depends on whether every subscriber gets the same deadline or their own. The editor generates whichever you pick, already filled in with your ids.

One thing to know before you paste anything. A merge tag cannot go inside the image address. The address is signed, and the signature covers every part of it, so if Iterable swaps a name into it after signing, the signature no longer matches and every subscriber gets the fallback graphic instead of your timer. It happens quietly, because the image service always answers with a valid picture rather than an error. Both snippets below put the merge tags in the link and the alt text, where they belong and where they work.

One image for the whole send

On every plan, including the free one. Everybody requests the same address, and the clock is worked out at the moment each person opens, which is what lets one address show a different time to every reader. The name and the code go in the link and the alt text.

<a href="https://yourstore.com/sale?code={{couponCode}}" target="_blank" rel="noopener">
  <img src="https://img.emailtimer.app/i/k7mQ2pXd.gif?w=w_8ha3fq&v=3&sig=YOUR_SIGNATURE" alt="{{firstName}}, your 25% off ends at midnight tonight" width="600" height="200" border="0" style="display:block; width:100%; max-width:600px; height:auto; border:0;" />
</a>

A different image for each subscriber

On Growth and Agency. Generate one signed address per subscriber, import the column into Iterable as a contact field called etImageUrl, and point the snippet at that field. This is the only way a deadline that differs per subscriber can work, because the deadline is inside the signature too. A contact whose field is empty gets no image, so check the field is filled across the whole segment before you send.

<a href="https://yourstore.com/sale?code={{couponCode}}" target="_blank" rel="noopener">
  <img src="{{etImageUrl}}" alt="{{firstName}}, your 25% off ends at midnight tonight" width="600" height="200" border="0" style="display:block; width:100%; max-width:600px; height:auto; border:0;" />
</a>

The addresses come from the batch endpoint in the REST API, or from a CSV export if you would rather not write code.

Setting it up in Iterable

Four steps, and the longest one is deciding what the timer should look like.

  1. 1

    Design your image asset

    Set your visual theme, expiration state image, and dynamic parameter fields.

  2. 2

    Copy Iterable Handlebars snippet

    Get code formatted with {{firstName}} and nested profile parameters.

  3. 3

    Paste into Iterable template

    Insert an HTML block in Iterable template editor and paste the embed snippet.

  4. 4

    Verify with user data preview

    Use the preview panel in Iterable to view real user payload substitution.

Things that only matter in Iterable

Iterable uses Handlebars syntax for profile data and event payloads. Handlebars helpers can format a date for the alt text or the body copy. A date drawn inside the image comes from an address signed for that user, not from a helper inside the address.

What your Iterable subscribers will actually see

Apple Mail caching retains image state from delivery. In journey automations, count evergreen timers from send time rather than from open, so the delivery prefetch does not shorten the window.

What each client is documented to do

Email client Fetch moment Cache lifetime GIF animation What EmailTimer.App does Basis
Apple Mail (iOS 15+, macOS Monterey+) Apple Mail Privacy Protection (MPP) Delivery time (pre-fetched by Apple server) Testing reports 2 to 3 days Full 30-second live animation The timer counts down from the time remaining at delivery. A fixed deadline, such as 23:59 UTC, is still the right deadline. Documented by Apple
Gmail (web, iOS, Android) Google image proxy First open by recipient Not published by Google Full 30-second live animation First open displays a real-time countdown. A re-open can be served from the copy the proxy already holds. Documented by Google
Outlook on Windows (2016 to 2024) Word rendering engine Open time Not documented First frame only (static image) Frame 1 is a complete image with the time left at the fetch, so a reader who sees only that frame sees a correct still countdown. Expected, not yet documented or tested
Outlook on the web and mobile (iOS, Android) Native browser or app engine Open time Not documented Full 30-second live animation Expected to play the animation, 30 frames at one frame per second by default. Expected, not yet documented or tested
Yahoo Mail and AOL Yahoo image proxy Open time Not documented Full 30-second live animation Expected to fetch the image when the message is opened and play the animation. Expected, not yet documented or tested

The Apple and Gmail rows rest on Apple's and Google's published documentation and on third-party testing. Neither company publishes a cache lifetime: Apple documents the prefetch, Google documents the proxy, and the two to three days is FreshInbox's 2021 testing. The Outlook and Yahoo rows are what we expect those clients to do, with no vendor document behind them. No row comes from a test by us yet, and we will publish dated screenshots when we have them. Sources: Apple on Mail Privacy Protection, Google on the Gmail image proxy, FreshInbox on Mail Privacy Protection image caching.

Iterable in practice

Iterable countdown timer, per user, with Handlebars

By Danish Mohammed, founder. , updated 7 min read

An Iterable countdown per user is an image whose address was signed for that user before the send and written to a user profile field. Handlebars puts the field whole into the image source, {{profile.etImageUrl}}, and personalizes the link and the alt text around it. Nothing Iterable computes at send time goes inside the address, because every parameter in it is signed.

Iterable’s own help centre carries a guide to adding someone else’s countdown timer. It is a good map of where the snippet goes. Two of its advanced tips break a signed timer, though, and one of them also puts each recipient’s email address into an image URL. This page is one of four for the enterprise ESPs: Marketo Engage, Oracle Responsys and Oracle Eloqua follow the same rule in their own syntax, and the enterprise guide covers the vendor decision around all of them.

Does Iterable have its own countdown timer

I found no timer block in Iterable’s documentation. What its help centre offers instead is integration articles, and the one for timers is Iterable’s page for a third-party timer vendor, “Sendtric + Iterable Integration”, read on 23 September 2026. It describes the integration as “a quick and easy way to add countdown timers to emails that contain time-sensitive products, sales, or events.”

The article’s setup steps apply to any timer image. Open the template, “select the HTML option in the Content tab”, drag the box to where the timer should appear, and paste the code into the Content Properties section for that HTML block. It also gives a wrapper for centring: a table with align="center" around the code.

The two tips that do not carry over

The article’s first advanced option is a dynamic timer. It appends ?to={{timestamp}}+86400 to the timer’s URL, so Iterable writes the send time plus a day into the address.

Its second option is a unique timer per user, keyed on “any unique user property”. It names {{entity_id}} and {{email}} as two options, and its code example uses ?k={{email}}, which puts each recipient’s email address in an image request.

Neither works with a signed address, and I would avoid the second on any timer. The HMAC signature on a timer address here is taken when the address is made, and it covers every parameter. A timestamp or an email address that Iterable writes in at send time leaves the signature out of step with the address. Every recipient then gets a grey “image unavailable” card, served with HTTP 200, and no error is raised anywhere. A per-user address from here carries an opaque recipient token instead, so no personal data travels in the image URL.

What the first tip was for, a window counted from the send, has its own mode here. The send instant is signed into the address when the address is minted: the batch API and the recipient list export both take a sent value, either now or a timestamp with an offset. The picture then counts down a fixed window from that moment, for as long as the mail sits in the inbox. The instant is whatever you sign, so mint close to the send: for a workflow that reaches users over weeks, mint each address through the API as the user enters, with sent set to now, rather than signing a whole list on day one.

A win-back countdown headed Come back on the price you were paying, reading 01 days 21 hours 00 minutes 00 seconds, with a Restart my plan button
A 72-hour window counted from a send at 09:00 UTC on 22 September, rendered by the product's engine a day and three hours later. The send instant was signed into the address, not written in by Iterable.

Iterable can compute an HMAC at send time. Its Handlebars reference includes hmacSHA1, which uses “the HMAC Secret specified in Project > Settings”. A timer address here needs HMAC-SHA256 with your workspace’s own secret, which that helper cannot produce, so the signing has to happen outside Iterable. That also keeps the secret out of your templates.

Where Handlebars may personalize the snippet

Diagram of the timer snippet in Iterable Handlebars. The link, carrying a coupon code, and the alt text, with a first name, are marked as safe to personalize. The image source is profile.etImageUrl, one field holding a complete signed address, marked whole only.
The three slots in the snippet, and which of them Handlebars may fill.

Campaign mode needs nothing from Iterable at all. Publish the timer, copy its signed address, and paste the snippet into the HTML block. The free plan includes this. Because the time left is drawn at the moment each mail client fetches the image, one address gives every reader the right number for their own open.

A per-user deadline needs one signed address per user, made before the send. They come from the REST API’s batch endpoint, up to 10,000 per call, or from a recipient list uploaded as a CSV and exported with one address per row, and both start at Growth. Write each address to a user profile field such as etImageUrl, the way you already write profile fields, and point src at that field.

Five-step diagram. Your data holds a deadline and a key per user. EmailTimer.App signs one address per user before the send. The address is stored in a profile field on the Iterable user, such as etImageUrl. At the send, Handlebars writes the field whole into src, with a fallback address if it is empty. At the open, the image service reads the token and draws that person's deadline. A warning says Iterable must not write a value into part of the address.
Where the per-user deadline is fixed, and what Iterable does with it.

The dashboard’s publish screen writes the Iterable form when you choose Iterable and a different image for each recipient. It uses the short {{etImageUrl}}; change it to {{profile.etImageUrl}} in any campaign an event or an API call triggers, for the reason in the next section.

The Snippet tab of the publish dialog with Iterable chosen and A different image for each recipient selected. The code block shows an image tag whose src is the etImageUrl Handlebars field and a link carrying the couponCode field
The publish dialog's Iterable snippet, per recipient, captured from a local test instance of the dashboard.

Handlebars rules that decide whether it renders

Four details from Iterable’s documentation matter for an image source.

Case. Iterable says “Event and user profile field names are case-sensitive.” A field created as EtImageUrl does not answer to {{etImageUrl}}.

Event fields win. When a triggering event or API call “contains a field with the same name as a field on the user’s profile, Iterable displays the value from the event field.” If an event could ever carry a field with that name, write {{profile.etImageUrl}}, the form Iterable documents for reading the profile value.

Quotes. The Handlebars overview says that inside a double-quoted HTML attribute, nested string literals take single quotes, because “Double nested quotes break Handlebars syntax.”

Defaults. Its own example of that rule is an image: <img src="{{defaultIfEmpty product.imageUrl 'https://cdn.example.com/fallback.png'}}">. The same helper gives a user with an empty field a working image rather than a broken one.

Put together, with the default pointing at the campaign address of a second template that has a fixed deadline:

<a href="https://yourapp.com/upgrade" target="_blank" rel="noopener">
  <img src="{{defaultIfEmpty profile.etImageUrl 'https://img.emailtimer.app/i/k7mQ2pXd.gif?w=w_8ha3fq&v=3&sig=YOUR_SIGNATURE'}}" alt="{{firstName}}, your offer ends soon" width="600" height="200" border="0" style="display:block; width:100%; max-width:600px; height:auto; border:0;" />
</a>

The overview also says double braces escape HTML and triple braces do not. An escaped ampersand in an attribute is decoded again by the mail client’s HTML parser. If you would rather not depend on that, {{{profile.etImageUrl}}} passes the address through unescaped. Iterable does not document triple braces around defaultIfEmpty, so test that combination before relying on it.

One more note from the reference. If you edit the HTML source, Iterable suggests commenting out Handlebars expressions that output nothing, such as #if blocks. It says not to comment out one that outputs a value, like a profile field: “Commenting out such an expression would prevent its value from rendering in the template.”

What your recipients will see

After delivery, Iterable is out of the picture and the mail client decides. Microsoft’s Outlook support page says “If only the first frame of the animation appears, you have animations, or animated GIFs, disabled.” A still timer from here reads correctly, because the first frame is a complete image with the time left already drawn.

Apple’s Protect Mail Activity “downloads remote content in the background by default”, so an Apple Mail reader can see the time left as it stood at delivery. In a workflow that sends at 03:00, that reader may see the 03:00 figure when they open at breakfast. The email client support page has the rest, taken from vendor documentation, since no timer here has been tested in a live inbox so far.

Test before you send

Iterable’s test message guide explains which data a proof uses. “To yourself” sends to you “using data from your Iterable profile to resolve any Handlebars expressions”. So your own profile needs a real signed address in etImageUrl, or the proof shows the default image.

Two other options help. “As random users” sends to you using data from random users on a list you choose. Sending from the Preview page is the more useful one. There, “Iterable uses the loaded user data when sending the test message, including any manual edits you have made.” Load a user, paste a real address into the field, send, and open the proof in two different mail apps.

Questions and answers

Does Iterable have a native countdown timer?

Not that I found. Iterable’s help centre documents countdown timers through a third-party integration article rather than a block of its own.

Can I use {{timestamp}} in the timer URL, as Iterable’s help article shows?

Not with a signed address. A value written into the address at send time breaks the signature, and every recipient gets the grey “image unavailable” card. Sign the send instant in when the address is minted, with the sent value, instead.

Why does my Iterable proof show the fallback or default image?

A proof sent to yourself resolves Handlebars from your own Iterable profile. If your profile has no signed address in the field, you get the default. Load a user on the Preview page, or fill in your own field.

Should I use {{profile.etImageUrl}} or {{etImageUrl}}?

Use the profile. form in any campaign triggered by an event or API call. Iterable gives an event field precedence over a profile field with the same name.

Which plan does an Iterable workflow need?

One deadline shared by everyone is on the free plan, with 5,000 image opens a month. A deadline per user needs addresses minted per user, which starts at Growth for $49 a month. Pricing lists what each tier adds.

Sources

Related

Campaigns to build in Iterable

Each playbook says which timing model the campaign needs, which snippet it takes, and what to get right before you send it.

Setting this up on another platform

The snippet is the same everywhere. Only the merge syntax changes, and each page below carries the exact syntax that platform expects.

All 21 platform setup guides

Put a timer in your next Iterable send

Free for 5,000 opens a month, $19 for 250,000, and the snippet above is the whole integration.