EmailTimer.App

Countdown timers and personalized images for Customer.io email

Your subscribers see how long is left on the offer, counted from the moment they open the message, and it goes into the Customer.io campaign you have already built. One snippet, in the merge syntax Customer.io 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 Customer.io image block.

Customer.io 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 Customer.io 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
{{customer.first_name}}
Coupon code
{{event.coupon_code}}
Deadline
{{event.expiration_date}}
Email address
{{customer.email}}

The snippet to paste into Customer.io

Put it in customer.io drag-and-drop html block or rich text editor. 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 Customer.io 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={{event.coupon_code}}" target="_blank" rel="noopener">
  <img src="https://img.emailtimer.app/i/k7mQ2pXd.gif?w=w_8ha3fq&v=3&sig=YOUR_SIGNATURE" alt="{{customer.first_name}}, 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 Customer.io as a contact field called et_image_url, 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={{event.coupon_code}}" target="_blank" rel="noopener">
  <img src="{{customer.et_image_url}}" alt="{{customer.first_name}}, 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 Customer.io

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

  1. 1

    Create template in EmailTimer.App

    Customize layout, typography, timer style, and dynamic data variables.

  2. 2

    Export Customer.io Liquid code

    Copy the ready HTML tag containing {{customer.first_name}} and custom event attributes.

  3. 3

    Add to campaign or broadcast

    In Customer.io, add an HTML block to your message and paste the snippet.

  4. 4

    Send a test to workspace profile

    Preview as a representative person or send a live test message from Customer.io.

Things that only matter in Customer.io

Customer.io supports Liquid for both customer attributes (customer.name) and event attributes (event.deadline). An event-specific deadline from a triggered workflow is different for every person, so it needs one signed image address per person rather than a tag inside the address.

What your Customer.io subscribers will actually see

Images are fetched by email client proxies. For onboarding and reactivation flows, dynamic per-recipient deadlines provide consistent urgency.

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.

Customer.io in practice

Customer.io countdown timer guide

By Danish Mohammed, founder. 5 min read

Customer.io is the rare platform that builds a countdown into its template language. It is also the platform with the most specific documented ceiling in this directory, and the ceiling is a number you can check yourself in thirty seconds.

Does Customer.io have its own countdown timer

Yes. There is a countdown Liquid tag. The Liquid syntax list describes it as something that “Creates a countdown timer in your message, helping you alert your audience to how soon an event they’re interested in is set to happen”. It takes a font size, a target time in YYYY-MM-DD hh:mm:ss (GMT) form, a foreground colour and a background colour as required parameters, with optional font, weight, locale, looping, resolution and frame count.

The Liquid recipes page shows a working call, and it is compact:

{% countdown point:64 font:roboto weight:light fg:000000 bg:f2f6f9 time:"2022-07-04 12:00:00 (GMT)" locale:en looping:true resolution:S frames:2 %}

The same page states the limit in one sentence: “The countdown timer GIF cannot contain more than 60 frames. This limits the size of the image in your messages and ensures that your message loads properly.”

Sixty frames is the constraint that decides everything else. With resolution:S, one frame is one second, so the animation covers sixty seconds and then stops. That is fine for a timer that reads in days and hours, where each frame is a much longer step. It is a real constraint for the seconds display that most people picture when they ask for a countdown, and it is the reason the recipe in the docs sets looping:true.

The design surface is narrow too. Colours arrive as hex values and the font weight “takes normal CSS font-weight values”, which is the extent of the styling the tag exposes. Anything your brand guidelines require beyond that has to come from an image.

Where the snippet goes

Customer.io offers four editors for email, and they differ in how much markup they will accept. The email basics page lists Design Studio, the drag-and-drop editor, the rich text editor and the code editor, and notes that layouts “are only available in our rich text or code editors”.

In the drag-and-drop editor, drop an HTML content block where the timer belongs and paste the image tag into it. The drag-and-drop FAQ is direct about the trade-off: you can add blocks of HTML, but “there is no way to view all body HTML like there is with the code editor”. If you want the whole message under version control, use the code editor and paste the tag inline.

Liquid personalization is the usual two namespaces. Customer.io documents customer attributes as {{customer.<attribute_name>}} and event attributes as {{event.<attribute_name>}}, with a default filter for missing values, as in their own example {{ customer.plan_name | default:"custom" | capitalize }}. “The default filter only works with our latest version of liquid”, so an older workspace has to use an if-else block instead.

A per-person deadline cannot be appended to the image URL as a Liquid tag. Every query parameter is inside the signature, so a value substituted after signing fails verification for everyone in the send. Write a pre-signed URL to a person attribute and read it back:

<img src="{{customer.et_image_url}}" width="600" height="200" border="0" alt="Your seat is held for a little longer" />

What breaks in automations and flows

Customer.io campaigns are long-lived by design, which is the trait that turns a fixed deadline into a liability. A time: value hard-coded into a Liquid countdown inside an onboarding campaign is correct for one week and misleading for the rest of the year. Anything that runs on a trigger wants a deadline computed from the person’s own entry instant.

The 60-frame cap interacts with this badly. A seconds-resolution timer inside a journey animates for one minute per open, so a recipient who scrolls back to the message an hour later sees the animation finish quickly and stop. Looping hides the symptom and introduces another one, because a countdown that jumps back to its opening number reads as broken to anybody watching it.

Preview data is the third trap. Customer.io’s test send replaces Liquid statements with data from whichever profile you pick in the Sample Data panel, so a profile without your URL attribute produces an empty source attribute. Pick a profile that has been through the same integration that writes the attribute in production.

What your recipients will see

The GIF that Customer.io generates and the GIF that an image service generates are both subject to the recipient’s mail client, which has the final say. Classic Outlook on Windows draws HTML with the Word engine and shows one frame of an animated GIF instead of playing it. Apple Mail with Mail Privacy Protection fetches remote images at about the time a message is delivered, so the number reflects delivery. Gmail proxies images and can return a copy it already holds when the same person opens the mail again.

That is documented client behaviour rather than a render I have watched, and the per-version table is on the email client support page. Put it next to the 60-frame cap and the resolution choice makes itself. A days-and-hours timer stays inside the frame budget and stays readable when it is frozen at frame one. It also survives a proxy serving an hour-old copy, because an hour barely moves the display.

Test before you send

Customer.io’s testing page gives the exact sequence. Choose a person from the Sample Data panel, because “Your test send will replace customer liquid statements with this person’s data”. Then click Send test, “Enter up to 25 email addresses. Separate multiple email addresses with commas”, and choose whether the subject line carries a [TEST] marker.

Use two of those 25 addresses on Gmail and Outlook. The preview pane confirms that Liquid resolved. Only a delivered message confirms that a mail client fetched the image and drew it the way your design assumed.

Questions and answers

What is the 60-frame limit on the Customer.io countdown?

It is a documented ceiling on the GIF the countdown tag produces. The practical reading is that a seconds display stops moving after a minute, so pick days and hours unless the whole message is about the last minute.

Can I style the native countdown to match a brand palette?

Only within the parameters the tag exposes, which are a font family, a weight, a font size and two hex colours. A layout that needs more than that has to be rendered as an image.

How do I give each person their own deadline?

Write a pre-signed image URL to a person attribute, then use {{customer.et_image_url}} as the image source. The deadline is inside the signed URL, so a triggered campaign can set it per entry.

Which editor should the snippet go in?

Either the drag-and-drop editor, using an HTML content block, or the code editor. The code editor is the better choice when you want to see the whole message body as markup.

Does anything here need a developer?

No, though minting per-person URLs from the same service that writes your attributes needs the REST API, which is on Growth and Agency. The free plan covers 5,000 image opens a month with no watermark, and the tiers are on pricing.

Sources

Related

Campaigns to build in Customer.io

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 Customer.io send

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