appscript.dev
Automation Intermediate Slides Sheets Drive

Generate sales-enablement decks per segment

Tailor Northwind's messaging slides by audience segment — fintech, healthcare, retail.

Published Dec 28, 2025

Northwind sells to three very different segments — fintech, healthcare, retail — and a generic pitch deck lands flat in all of them. The messaging team has the right ammunition: a pain-point and a case study for each segment, kept in a small Segments Sheet. What they don’t have is the patience to copy the master deck three times and find-and-replace those fields, especially when the case study changes mid-quarter and every deck needs another pass.

This script does the copying for them. It walks the Segments Sheet, clones the master template once per segment, and stamps the segment-specific text across every slide in the new deck. Add a fourth segment to the Sheet and re-run the script; a deck appears in the same folder, with the same layout, ready for the next sales call.

What you’ll need

  • A master Slides template containing the layout used across every segment. Anywhere the segment, pain point, or case study should appear, write {{segment}}, {{painPoint}}, and {{caseStudy}}. Placeholders can appear on as many slides as you like — every slide is scanned.
  • A Segments Sheet with headers segment, painPoint, caseStudy in row 1 and one row per audience. The segment value goes into the filename, so keep it human-friendly.
  • A Drive folder where the generated decks land. Keep it separate from the master so deleting old runs never touches the template.

The script

// The master template — the layout every per-segment deck is cloned from.
const TEMPLATE = '1abcSalesTemplateId';

// The Sheet listing every audience segment to generate a deck for.
const SEGMENTS = '1abcSegmentsId';

// The Drive folder where the generated decks land.
const OUTPUT = '1abcSalesDecksFolderId';

/**
 * Reads the Segments Sheet and produces one deck per segment,
 * tailored to its pain point and case study.
 */
function generateSegmentDecks() {
  // 1. Read every segment as a plain object keyed by the headers.
  const segments = readSheet(SEGMENTS);
  if (!segments.length) {
    Logger.log('No segments defined — nothing to generate.');
    return;
  }

  const folder = DriveApp.getFolderById(OUTPUT);

  // 2. For each segment, copy the template into the output folder and
  //    replace the placeholders across every slide.
  let made = 0;
  for (const s of segments) {
    if (!s.segment) continue; // skip blank rows

    const copy = DriveApp.getFileById(TEMPLATE)
      .makeCopy(`Sales — ${s.segment}`, folder);
    const deck = SlidesApp.openById(copy.getId());

    for (const slide of deck.getSlides()) {
      slide.replaceAllText('{{segment}}', s.segment);
      slide.replaceAllText('{{painPoint}}', s.painPoint || '');
      slide.replaceAllText('{{caseStudy}}', s.caseStudy || '');
    }
    made++;
  }

  Logger.log(`Generated ${made} segment deck(s) into ${folder.getName()}.`);
}

/**
 * Reads a single-tab Sheet into an array of objects, using row 1 as keys.
 */
function readSheet(id) {
  const [h, ...rows] = SpreadsheetApp.openById(id).getSheets()[0]
    .getDataRange().getValues();
  return rows.map((r) => Object.fromEntries(h.map((k, i) => [k, r[i]])));
}

How it works

  1. generateSegmentDecks reads the Segments Sheet through readSheet, which turns each row into an object keyed by the header names. If the Sheet is empty, the script logs and exits.
  2. It resolves the output folder once, outside the loop, so the script does not pay for the folder lookup on every iteration.
  3. For each segment row, it skips records without a segment name (those are usually drafts) and otherwise copies the template into the output folder with a meaningful name like Sales — Fintech.
  4. It opens the new deck and walks every slide, calling replaceAllText for each of the three placeholders. Running across all slides means the template can use the same placeholder on the title, the body, and a closing slide — every occurrence gets replaced.
  5. Missing pain points or case studies fall back to an empty string, so a half-finished row produces a deck with a gap rather than the literal undefined showing through.
  6. It logs the number of decks created, which is the quickest sanity check after a run.

Example run

A Segments Sheet with these rows:

segmentpainPointcaseStudy
FintechCompliance slows shippingBoreal Bank — release cycle 6w → 2w
HealthcarePatient data fragmentedCalderwood Trust — single record across 3 sites
RetailCart abandonmentCarve Coffee — checkout drop-off down 18%

Produces three decks in the output folder:

  • Sales — Fintech, with the Boreal Bank case study and the compliance pain point woven through.
  • Sales — Healthcare, with the Calderwood Trust story.
  • Sales — Retail, with the Carve Coffee number.

Each deck is otherwise identical to the master in layout, fonts, and non-placeholder content.

Run it

This is an on-demand job, run when the messaging team updates the Sheet:

  1. In the Apps Script editor, select generateSegmentDecks and click Run.
  2. Approve the authorisation prompt the first time.
  3. Open the output folder in Drive to find the new decks.

Watch out for

  • Re-running the script makes another copy of every deck. The originals are not deleted, so you can end up with Sales — Fintech and Sales — Fintech (1) in the same folder. Either delete the old run first, or add a check that calls folder.getFilesByName(name).hasNext() and skips segments whose deck already exists.
  • replaceAllText is case-sensitive. Keep your placeholders as {{segment}} everywhere — {{Segment}} and {{segment }} (with a trailing space) will silently miss the replacement.
  • For a more personalised version of the same idea — one deck per individual prospect rather than per segment — see Create personalized pitch decks at scale.
  • The script reads the whole Sheet at once, which is fine for the handful of segments most teams maintain. If you ever push this past a few dozen rows, expect to hit the six-minute execution limit and split the work across multiple runs.

Related