appscript.dev
Automation Intermediate Slides

Build a Slides-based countdown timer

Embed a live countdown timer in a Northwind deck — refreshed via a scheduled script.

Published Nov 30, 2025

Northwind has a product launch coming, and the team wants a visible reminder — a countdown on the deck that runs on the office screen. Slides has no live timer of its own, so the obvious approach is to retype “42 days to go” by hand each morning. That lasts about a week before someone forgets and the deck quietly goes wrong.

This script keeps the countdown honest. The title slide carries a {{countdown}} placeholder; a scheduled script works out the time left until the launch date and rewrites the placeholder on every run. Leave the deck open on the screen and the number updates itself, with no one touching the slide.

What you’ll need

  • A Google Slides deck with the literal text {{countdown}} on the first slide, where the timer should appear.
  • The deck’s file ID, from its URL.
  • The target date and time you are counting down to.

The script

// The deck holding the countdown slide.
const COUNTDOWN_DECK = '1abcCountdownDeckId';

// The moment being counted down to (UTC).
const TARGET = new Date('2026-09-15T18:00:00Z'); // launch date

// Milliseconds in a day and an hour, named for readability.
const MS_PER_DAY = 86400000;
const MS_PER_HOUR = 3600000;

/**
 * Works out the time left until TARGET and rewrites the {{countdown}}
 * placeholder on the first slide of the deck.
 */
function refreshCountdown() {
  const deck = SlidesApp.openById(COUNTDOWN_DECK);
  const slides = deck.getSlides();

  // Bail out if the deck somehow has no slides.
  if (!slides.length) {
    Logger.log('Deck has no slides — nothing to update.');
    return;
  }

  const slide = slides[0];

  // Time left, clamped at zero so a past date never shows a negative.
  const remaining = Math.max(0, TARGET - new Date());

  // Break the remaining milliseconds into whole days and hours.
  const days = Math.floor(remaining / MS_PER_DAY);
  const hours = Math.floor((remaining % MS_PER_DAY) / MS_PER_HOUR);

  // Swap the placeholder for the formatted figure.
  const text = remaining === 0 ? 'Launched!' : `${days}d ${hours}h`;
  slide.replaceAllText('{{countdown}}', text);
  Logger.log('Countdown set to: ' + text);
}

How it works

  1. refreshCountdown opens the deck and reads its slides, stopping early if the deck is empty.
  2. It takes the first slide, which is where the {{countdown}} placeholder lives.
  3. It subtracts the current time from TARGET to get the milliseconds remaining, and clamps the result at zero with Math.max so a date in the past never produces a negative number.
  4. It converts that span into whole days and leftover hours using the named MS_PER_DAY and MS_PER_HOUR constants.
  5. It builds the display text — "42d 6h" style while the date is in the future, or "Launched!" once the target has passed.
  6. replaceAllText swaps the {{countdown}} placeholder for that text, and the script logs the result.

Example run

With TARGET set to 15 September 2026 and the script running on 25 May 2026, the first slide changes like this:

BeforeAfter
{{countdown}} until launch113d 4h until launch

An hour later the next scheduled run rewrites it to “113d 3h”, and so on down to the day itself, when it reads “Launched!”.

Trigger it

Run the refresh on an hourly timer so the figure stays close to current:

  1. In the Apps Script editor, open Triggers (the clock icon).
  2. Add a trigger for refreshCountdown.
  3. Choose a time-driven trigger, hour timer, every hour.

For the countdown to be seen, keep the deck open in Present mode on the office screen.

Watch out for

  • replaceAllText consumes the placeholder. After the first run the slide holds a real figure, not {{countdown}}, so later runs find nothing to replace. Keep a fixed prefix or suffix the script can target instead — for example always set the line to Launch: {{countdown}} and replace the whole line each run, or store the previous value and replace that.
  • The placeholder text must be exact. A space added by autocorrect, or a placeholder split across two text runs, will silently fail to update.
  • Resolution is days and hours — it never shows minutes. An hourly trigger matches that; a finer countdown would need a tighter trigger and a quota check.
  • TARGET is hard-coded in UTC. If Northwind is in another timezone, set the time accordingly or the countdown will be off by the offset.
  • A presented deck may cache its content. Most presenter views poll for changes, but if the screen looks stale, reload the deck on that machine.

Related