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
SegmentsSheet with headerssegment,painPoint,caseStudyin row 1 and one row per audience. Thesegmentvalue 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
generateSegmentDecksreads theSegmentsSheet throughreadSheet, which turns each row into an object keyed by the header names. If the Sheet is empty, the script logs and exits.- It resolves the output folder once, outside the loop, so the script does not pay for the folder lookup on every iteration.
- 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. - It opens the new deck and walks every slide, calling
replaceAllTextfor 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. - 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
undefinedshowing through. - It logs the number of decks created, which is the quickest sanity check after a run.
Example run
A Segments Sheet with these rows:
| segment | painPoint | caseStudy |
|---|---|---|
| Fintech | Compliance slows shipping | Boreal Bank — release cycle 6w → 2w |
| Healthcare | Patient data fragmented | Calderwood Trust — single record across 3 sites |
| Retail | Cart abandonment | Carve 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:
- In the Apps Script editor, select
generateSegmentDecksand click Run. - Approve the authorisation prompt the first time.
- 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 — FintechandSales — Fintech (1)in the same folder. Either delete the old run first, or add a check that callsfolder.getFilesByName(name).hasNext()and skips segments whose deck already exists. replaceAllTextis 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
Extract all deck text into a sheet
Pull text out of every slide for review, translation, or copy-editing.
Updated Jan 4, 2026
Insert chapter divider slides from an outline
Add section-break slides between chapters in a Northwind deck.
Updated Dec 21, 2025
Build a deck accessibility checker
Flag missing alt text, low contrast, and tiny fonts across a Northwind deck.
Updated Dec 14, 2025
Drive menu and price-list signage from a Sheet
Generate display slides for a Northwind venue — menus or price lists driven by a Sheet.
Updated Dec 7, 2025
Build a Slides-based countdown timer
Embed a live countdown timer in a Northwind deck — refreshed via a scheduled script.
Updated Nov 30, 2025