The code in your scheduled email expired yesterday. What would catch it before it sends?

A campaign gets scheduled on Monday. On Wednesday the offer changes. On Friday the email goes out with a code that no longer works, and you find out from customer replies.

The fix I built is boring on purpose. One offers sheet is the source of truth: code, discount, start date, end date. Then, before each send:

  1. Pull the email content and list every code, offer and date in it. AI is good at finding these in messy HTML.
  2. Compare each one to the sheet and to the send date in a Code node. The model finds, the code judges.
  3. Throw out anything the model says it found that is not actually in the email text, so a misreading never reaches your report.

While you are in there, test every link and image too.

My full version runs every hour on scheduled Klaviyo campaigns and reports to Slack. It only reads, so it never edits a campaign. You can find it in the n8n template library under my name.

Who checks your scheduled emails before they go out: nobody, the person who built them, a second person, or an automated check? And what is the worst thing you have seen go out in a campaign?

The likely cause is that the send step trusts the scheduled content instead of re-checking it against the offers sheet at send time. An offer can change after scheduling, so a check that ran on Monday will not catch a Friday expiry.

Put a gate directly before the email step, using the sheet as the source of truth:

  1. Use a Google Sheets node to read the offers sheet, with columns for code and end date.
  2. Match the code in the scheduled email to the row for that code, so you are checking the current end date, not the date from when the email was scheduled.
  3. Add an IF node after the lookup. Send rows where the end date is on or after the send date to the email step, and send rows where the end date is before the send date to a separate branch.
  4. On the expired branch, use a Google Sheets node with the Append operation to add the code, offer and end date to a review sheet, and send an alert to Slack so the team can fix or replace the code. Do not let that branch reach the email step.
  5. Keep the send date as a single value for the whole run, so every row is judged against the same date.

To test it, run the workflow with two codes: one that expired yesterday and one that is still valid. The expired code should appear in the review sheet and no email should go out for it, while the valid code should pass through to the email step.