Evergreen Deadlineby Tofu Labs

Setup guide

About 10 minutes, start to finish. Your dashboard fills in your own campaign code in every snippet below, so you can copy from there.

1. Create a campaign

Open the dashboard and press New campaign. Choose:

Protecting your monthly allowance. Your campaign code is visible in your page's source, so with the default start setting anyone could make up addresses and start deadlines that count toward your plan. We limit that: each network can start at most 20 new deadlines an hour per campaign, and a campaign can start at most 60 in 10 minutes from pages (more on bigger plans). Email images opened through the mail apps' own image servers (Gmail, Apple Mail, Yahoo) have their own, larger limits: 500 an hour per image server and 300 in 10 minutes per campaign (on Creator 750, on Business 6,250). When a limit is reached, nobody gets a made-up timer: new people see your page without a countdown and an email image that says "Limited-time offer" (the same as when your plan is full), and their deadline starts on a later visit or open once the limit has passed. People who already have a deadline aren't affected. For full protection, choose Only from my email tool: then only your private webhook address starts deadlines. Webhooks and imports have no hourly limit.
Device-only deadlines. You can also give visitors with no email a deadline on their device. It lives only in that browser, so opening the page in a private window or another browser starts a new one. That's fine for ads and cold traffic; for an offer you want to close for good, leave it off (the default) and send people with no deadline to your sign-up page.

2. Put the script on your offer pages

Paste this in the <head> of your sales page and checkout page (in WordPress, use the plugin instead):

<style>html:not(.evd-ready) [data-evd-when=expired],html:not(.evd-ready) [data-evd-when=none]{display:none!important}</style>
<script src="https://tofulabs.app/deadlines/t.js?v=637c1d61b7" data-campaign="YOUR_CAMPAIGN_ID"></script>

The first line keeps your "ended" and "no deadline" sections (below) hidden until our script has checked the visitor, so if the script can't load (a privacy extension, an outage), people see only your offer.

Then put a timer where you want one:

<div data-evd-timer></div>

That draws the same timer as your email: the words above it, then days, hours, minutes and seconds in your campaign's look. For one line of text instead, use <span data-evd-timer data-evd-style="inline"></span>. To leave the words above the timer out on one timer, add data-evd-heading="off" (or untick it in the campaign's settings for every page).

Optional extras

Check your page before you send

Open your offer page with ?evd_preview=1 at the end of its address (for example https://yoursite.com/offer?evd_preview=1). You'll see the timer at its full length with a small "Preview" label. It never redirects you, saves nothing and doesn't count toward your plan, so you can check the page as often as you like. Links to your checkout carry the preview along.

3. Link from your emails with the subscriber's email

Add evd_email= and your email tool's merge tag to every link that goes to the offer. The script reads it, then removes it from the address bar. If the script can't load at all (for example a browser extension blocks it), the address stays as it was; the WordPress plugin removes it in that case too.

https://yoursite.com/offer?evd_email={{ subscriber.email_address }}

Use your tool's own tag for the email address:

Email toolMerge tag
Kit (ConvertKit){{ subscriber.email_address }}
Mailchimp*|EMAIL|*
ActiveCampaign%EMAIL%
MailerLite{$email}
Brevo{{ contact.EMAIL }}
Klaviyo{{ email }}
About analytics. Until our script removes it, the email address is part of the page address. Analytics tags that run before it (for example Google Analytics' page view) and your server's logs can record it. Put our script above your analytics tag in the <head>, and in Google Analytics turn on Data redaction for email addresses (Admin → Data streams → your stream → Redact data), which new streams have on already.

4. Add the countdown image to your emails

Insert an image (or an HTML block) with this address, using the same merge tag:

<img src="https://tofulabs.app/deadlines/e/YOUR_CAMPAIGN_ID/{{ subscriber.email_address }}.gif" width="480" alt="Time left on your offer">

The image shows days, hours, minutes and seconds left and ticks down for a minute while the email is open. Once the deadline has passed it shows your "it's over" words. It's worked out fresh each time the email is opened, so an email opened late shows the right time. Outlook on Windows doesn't play animations: it shows the first frame, which is still the right time.

In your email editor, where the merge tag isn't filled in yet, the image shows a sample timer labelled "Preview: each subscriber sees their own time left". Each real subscriber sees their own.

Sending to a whole list at once? Start deadlines from your email tool's webhook (step 5). With the default start setting, a big broadcast's first opens all arrive within minutes, and past the start limits above some people would see "Limited-time offer" instead of a timer until a later open. A webhook step before the send starts everyone's deadline with no limit. It also avoids early starts: some inboxes (Gmail, Apple Mail) download images as the email arrives, which can start a reader's clock before they open it; a webhook start gives everyone the same, known starting point.
Some email apps (Apple Mail, Gmail) download images when the email arrives. If your campaign starts on the first email open, the clock can start a little before the person reads it. The deadline still works the same way; it just starts a little earlier.

5. Start deadlines from your email tool (optional)

Every campaign has a private webhook address (in the dashboard under Set it up). When your email tool sends it a subscriber, their deadline starts right then, before they open anything. Sending the same person again changes nothing.

Kit

  1. In Kit, open Apps, find Send a Webhook (Kit's own app) and click Install.
  2. Open Automations → Visual automations and edit the automation people enter when they should get the offer (for example one that starts with Tag is added or Joins a form).
  3. Click the + where the deadline should start, choose Action, then Send a Webhook → Webhook.
  4. Paste your campaign's webhook address into Webhook URL, give it a Webhook Name such as "Start deadline", and click Add Action. Put it before the email that shows the countdown.

Kit's Send a Webhook app and its Webhooks page (Automate → Webhooks, for events like "Tag is added") need a paid Kit plan. On Kit's free plan, let the deadline start on the first email open or click instead: that needs no setup at all.

Kit runs automation steps in batches, so the first webhook call can arrive a few minutes after someone enters the automation. To see it arrive, open the campaign's Set it up tab: Recent webhook calls lists the last 30 calls, who they were for and what happened (a deadline started, one already running, or the reason it was refused).

ActiveCampaign

Edit your automation, click + where the deadline should start, and in Add an action choose Workflow → Webhook. Paste the address and save. Webhook actions are on ActiveCampaign's Plus plan and up.

Mailchimp

Click Audience, then More options → Audience settings → Manage webhooks → Create webhook. Paste the address as the Callback URL, tick only Email subscribes, and click Create webhook. Every new subscriber gets a deadline right away.

MailerLite

In your automation, click + where the deadline should start and choose Webhook. Paste the address as the Webhook URL. MailerLite also asks for its Secret Key (from its Integrations page); we don't need it.

Zapier, Make and everything else

Send the subscriber's email to the address as JSON, a form or ?email=: a "Webhooks by Zapier → POST" step or a Make "HTTP → Make a request" step with a field called email. The response tells you the deadline: {"ok":true,"ends":1760112000000,...}.

Every call, from any tool, shows up under Recent webhook calls on the campaign's Set it up tab, with what came of it.

Set the end time yourself

Add ends= (or deadline=) to give a new person a set end instead of the campaign length, for example when you move people over from another tool: [email protected]&ends=2026-11-02T18:00. It takes ISO dates like 2026-11-02T18:00:00Z, 2026-11-02 18:00, 11/02/2026 6:00 PM (month first), a date alone (11:59 PM that day) or Unix time. Times without a zone use the campaign's time zone. A person who already has a deadline keeps it; one that has already ended is saved as ended and doesn't count toward your plan.

6. Put the date in your Kit emails (optional)

In the dashboard, open Account and paste a Kit v4 API key (in Kit: Settings → Developer → API keys → Add a new key). We keep it encrypted. From then on, when someone's deadline starts, we write two custom fields on their Kit subscriber:

Each campaign can use its own field names (in its settings: "spring" gives spring_text and spring_at), so two offers never overwrite each other. We create the fields in Kit for you. Give someone more time in the dashboard and their fields update too. When someone has only just joined, Kit can take a little while to finish saving them, so if Kit doesn't know them yet we try again: after 20 seconds, then over the next 3 hours (the Account page shows how many are waiting). If Kit refuses a write for good (a deleted key, someone who never becomes a Kit subscriber), the Account page lists it under Recent problems with their email address; they stay there until you clear them.

Give Kit a moment. Kit fills in an email when it sends it, and its webhook step can take a few minutes to run. In your automation, put a Delay of about 10 minutes between the Send a Webhook step and the first email that shows the date, and write the field with a fallback: {{ subscriber.deadline_text | default: "soon" }}. The countdown image needs neither: it's worked out when the email is opened.

7. Count sales (optional)

Put this on your thank-you page, after checkout:

<script src="https://tofulabs.app/deadlines/t.js?v=637c1d61b7" data-campaign="YOUR_CAMPAIGN_ID" data-sale data-amount="79" data-currency="USD"></script>

It counts one sale for the buyer (a reloaded thank-you page doesn't count twice), and never starts or changes a deadline. The amount and currency are optional; write the amount as a plain number like 49.00. It finds the buyer the same way as your offer pages: the deadline saved in their browser, a link with evd_t or evd_email, or ?email= if your checkout passes the buyer's email to the thank-you page. If the thank-you page is on your checkout's own domain, list the checkout in the campaign's "Other pages" so the visitor's deadline travels there.

Each campaign's Results tab shows new people per day for the last 30 days, sales, and the share of buyers who bought before their deadline.

8. People

The People tab lists the latest people (running, ended or bought) with their email address, and Export CSV downloads everyone: email, start, end, how it started, visits and what they bought. Click someone to help them: Give more time sets a new end for that one person, and Remove deletes their deadline so they start fresh the next time they arrive. If they bought, the sale stays in your Results (the Bought filter still lists it), but their email address is erased, so Remove also answers a request to delete someone's data. Nothing ever resets by itself.

People who started before 9 October 2026 show a short form of their email, like t•••[email protected], until they next open an email or visit your page. Visitors with no email show as "Device only".

Switching from Deadline Funnel

Bring your people over with the deadline they already have, so nobody mid-sequence gets a brand-new window.

  1. In Deadline Funnel, open your campaign, click Open Analytics, set the date range so it covers everyone who joined (the export only has people from the range shown), and click Export.
  2. Here, make a campaign with the same length, open its People tab and press Import CSV. Pick the file, check that the email and deadline columns are the right ones, and press Check the file. If the dates are written like 03/04/2026, we ask whether that's March 4 or 3 April (we work it out when a date like 13/04 settles it).
  3. You'll see how many people will be added, how many already have a deadline here (they keep theirs), each row we can't use and why (an impossible date like 31 April is refused, never moved to another day), and a few dates as we read them. Press Import.
  4. Swap the Deadline Funnel script and email images for ours (sections 2 to 4). Do it on the day you import, so both tools agree.

Writing a file yourself? Use the template in the import box: one email column and one end time written year first, like 2026-11-20 18:00 (ISO 8601), which can't be misread. Times without a time zone are read in the campaign's zone. People whose deadline is still running count toward this month's new deadlines; ones that already ended are free. Imported people aren't written to Kit's fields; if you use those, run the import, then send each person through your Kit webhook step with ends= (section 5) instead. You can also skip the file entirely and use ends= from Zapier or Make.

9. WordPress

Install the free Evergreen Deadline plugin and paste your workspace key in Settings → Evergreen Deadline. Then pick a campaign in the "Deadline Countdown" block, or in the Evergreen Deadline panel of the page editor's sidebar (Page tab), where you also set the redirect, the bar and "This is a thank-you page". To show content only while someone's deadline runs, after it ends, or to people with no deadline, use the Deadline content block or the shortcodes on the plugin page. The plugin also has fixed-date timers that work without an account.

Your account

Good to know