Generate product descriptions in bulk
Write SEO copy for an entire Northwind catalogue from a Sheet of names + specs.
Published Jul 22, 2025
A new Northwind catalogue arrives as a spreadsheet of product names and dry specs, and someone has to turn each row into a description that reads well and helps the page rank. Done by hand it is a slow, repetitive afternoon, and the later entries always read more tired than the first.
This script does the whole column at once. It walks the catalogue Sheet, and for every product still missing a description it asks Claude to write a tight, 40-word blurb from the name and specs. The tone is fixed in the prompt — for Northwind, confident and free of hype — so the hundredth description is as crisp as the first.
What you’ll need
- A Google Sheet with your catalogue: a header row, a
namecolumn, aspecscolumn, and an emptydescriptioncolumn for the output. - An Anthropic API key saved as
ANTHROPIC_API_KEYin Script Properties — see Store API keys and secrets securely.
The script
// The Sheet that holds the product catalogue.
const CATALOGUE_SHEET_ID = '1abcCatalogueId';
// Target length and tone for each description — change once, here.
const DESCRIPTION_WORDS = 40;
const DESCRIPTION_TONE = 'confident, no hype';
/**
* Writes a description for every catalogue row that has a name but
* no description yet.
*/
function generateDescriptions() {
// 1. Read the catalogue and map header names to column indexes.
const sheet = SpreadsheetApp.openById(CATALOGUE_SHEET_ID).getSheets()[0];
const [h, ...rows] = sheet.getDataRange().getValues();
if (!rows.length) {
Logger.log('Catalogue is empty — nothing to describe.');
return;
}
const col = Object.fromEntries(h.map((k, i) => [k, i]));
// 2. Walk the rows; describe each product that needs it.
let written = 0;
rows.forEach((r, i) => {
// Skip rows already described, or with no name to work from.
if (r[col.description] || !r[col.name]) return;
// 3. Build the prompt from the name, specs, length and tone.
const prompt =
'Write a ' + DESCRIPTION_WORDS + '-word product description for: ' +
r[col.name] + '. Specs: ' + r[col.specs] + '. ' +
'Tone: ' + DESCRIPTION_TONE + '.';
// 4. Write the result back into the description column.
sheet.getRange(i + 2, col.description + 1).setValue(callClaude(prompt));
written++;
});
Logger.log('Wrote ' + written + ' descriptions.');
}
/**
* Minimal Anthropic API call. The key lives in Script Properties — it
* is never pasted into the code.
*/
function callClaude(prompt) {
const key = PropertiesService.getScriptProperties()
.getProperty('ANTHROPIC_API_KEY');
const res = UrlFetchApp.fetch('https://api.anthropic.com/v1/messages', {
method: 'post',
contentType: 'application/json',
headers: { 'x-api-key': key, 'anthropic-version': '2023-06-01' },
payload: JSON.stringify({
model: 'claude-haiku-4-5-20251001',
max_tokens: 200,
messages: [{ role: 'user', content: prompt }],
}),
muteHttpExceptions: true,
});
return JSON.parse(res.getContentText()).content[0].text.trim();
}
How it works
generateDescriptionsopens the catalogue Sheet and reads every row, then builds acolmap from header names to indexes so the code stays readable.- If the Sheet has no data rows it logs that and stops before any API calls.
- For each row it skips anything already described or missing a name, so a re-run only fills the gaps and never overwrites finished copy.
- It assembles the prompt from the product name, its specs, and the shared
DESCRIPTION_WORDSandDESCRIPTION_TONEconstants — change those once and every description follows. - Claude Haiku writes the blurb. Haiku is the right call here: short marketing copy is fast, cheap work that does not need Sonnet’s reasoning.
- The result is written back into the
descriptioncolumn ati + 2to account for the header row and zero-based loop index.
Example run
Suppose the catalogue Sheet holds:
| name | specs | description |
|---|---|---|
| Northwind Drafting Lamp | LED, 5 brightness levels, USB-C, matte black | (blank) |
| Northwind Desk Mat | 90x40cm, cork base, water-resistant felt top | (blank) |
After a run the description column is filled with copy like:
| name | description |
|---|---|
| Northwind Drafting Lamp | A focused LED work light with five brightness levels and USB-C power. The matte-black finish sits quietly on any desk while the adjustable arm puts light exactly where you need it. |
| Northwind Desk Mat | A generous 90x40cm work surface with a water-resistant felt top and a cork base that grips. It protects your desk, softens your keyboard, and tidies the whole setup. |
A column of specs becomes a column of ready-to-publish copy.
Run it
This is an on-demand job — run it when a new catalogue lands:
- In the Apps Script editor, select
generateDescriptionsand click Run. - Approve the authorisation prompt the first time.
- Open the Sheet and review the descriptions before publishing.
To let the catalogue team trigger it from the Sheet, add a custom menu:
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('Catalogue tools')
.addItem('Generate descriptions', 'generateDescriptions')
.addToUi();
}
Watch out for
- A 40-word target is a guide, not a guarantee. Models land near the figure but rarely hit it exactly — if length must be precise, trim in review.
- Descriptions are only as good as the specs. A vague or empty
specscell gives Claude little to work with and the copy turns generic. - Re-running skips filled rows. To regenerate a description, clear its cell
first — otherwise the
r[col.description]guard treats it as done. - Large catalogues take time and tokens. Each row is one API call; a catalogue of thousands may need batching or a higher-rate plan to finish in one run.
- Claude does not check facts. It writes from the specs you give it — if a spec is wrong, the description will repeat the mistake confidently.
Related
Generate and test email subject lines
A/B test AI-written Northwind subject lines for open rate — outputs ranked by past performance.
Updated Mar 3, 2026
Build retrieval-augmented Q&A over your data
Answer Northwind questions grounded in your own Sheet data — pass relevant rows as context.
Updated Feb 27, 2026
Build an AI weekly-report narrator
Turn Northwind metrics into a written executive summary — numbers in, prose out.
Updated Feb 23, 2026
Build a multi-step AI agent workflow
Chain Claude prompts to complete a Northwind task end to end — research → draft → critique → finalise.
Updated Feb 11, 2026
Adapt marketing copy per region
Localise Northwind tone and references by market with AI — same message, regional flavour.
Updated Jan 30, 2026