AI for Product Descriptions: The 500-SKU Bulk Workflow

Generate product descriptions for a whole catalog: CSV in, JSON schema out, machine-checked, deduplicated, imported back. The bulk path vendors skip.

Difficulty
Intermediate
Time to Implement
1-2 days for the first run, under an hour per run after that
Potential ROI
About $1 in API tokens for 500 SKUs on Claude Haiku 4.5 via the Batch API — review time, not tokens, is the cost that matters
On this page

Every guide to AI product descriptions teaches you to write one description in a chat window. That is not the job. The job is 500 SKUs, and the chat window is the wrong shape for it.

Vendor blogs skip the bulk path because their business model depends on you staying inside their interface, paying per seat, one description at a time. This guide covers the other route: a CSV of raw attributes, a forced JSON schema, a batch API call, machine validation, a bulk import back into your store. It costs about a dollar in tokens for 500 products — and the tokens are not the expensive part. Most of this page is about the part that is.

The Challenge

A catalog is a scale problem wearing a writing problem's clothes.

  • The unit of work is the catalog, not the product. One good description is a pleasant afternoon. Five hundred is a project — and the moment you have 500 you also have 500 near-duplicates, 500 chances to make a false claim, and 500 rows to import without breaking your store.
  • Native AI tools are single-product tools. Shopify Magic is free across all plans and genuinely useful — and it works from inside one product's admin page, one description at a time. There is no bulk generation mode: a 500-SKU refresh through Magic is 500 page loads. (Shopify's Sidekick and third-party bulk editors can act across many products, but none of them gives you a schema, a validator, or a diffable artifact — which is the whole point of what follows.)
  • Your attribute data is worse than you think. The model can only write what the row contains. A row that says Men's Jacket, Outerwear, $189.00 cannot produce an honest description, and the model will not tell you that — it will invent the missing half.
  • Descriptions land in fields, not in a chat log. Title, short description, long description, bullets, meta description: five destinations with five different length limits. Free prose from a chatbot maps to none of them.
  • The failure modes are silent. A wrong description is not caught in review. It is caught in the returns queue, three weeks later, by a customer who bought a jacket because your site said it was waterproof.

How AI Solves It

The bulk workflow is a data pipeline, not a conversation.

  • A fixed JSON schema turns generation into a field-mapping problem. Instead of prose you have to parse, you get an object with title, short_description, bullets, long_description and meta_description — keys that map one-to-one onto columns in your import file. Modern APIs guarantee that shape by constraining decoding to the schema, so the output cannot come back malformed.
  • Batch endpoints halve the price and remove the rate-limit problem. Submit 500 requests as one asynchronous job, come back later, collect 500 results.
  • Grounding can be forced structurally. Make the model emit, alongside every bullet, the input attribute that bullet came from — then reject in code any bullet whose cited attribute is not in the row. Hallucination stops being something you hope about and becomes something you test.
  • The quality gate is mostly machine work. You cannot read 500 descriptions. You can run all 500 through length checks, forbidden-claim regexes, grounding checks and a near-duplicate detector in seconds, then read a meaningful sample of what survives.

What AI does not solve: the truthfulness of your attribute data, the sameness of 500 outputs from 500 near-identical prompts, and your legal responsibility for what the page says. Those are the three sections below that matter.

Three questions decide the tool: does it have an API, does it support a guaranteed JSON schema, does it have a batch discount. Chat interfaces fail the first — which is why the free tools most guides recommend are the ones you cannot use here.

Tool / modelRole in the pipelineSchema-guaranteed JSONBulk-ready
Claude (Haiku 4.5)The generation workhorseYesYes — Batch API, 50% off
Claude (Sonnet 5)Harder categories, gold-standard examplesYesYes
ChatGPT (GPT-5.5)Capable, meaningfully more expensive per SKUYesYes
Google Gemini (Gemini 3.5)Strong price/quality; good on image-derived attributesYesYes
DeepSeek (DeepSeek V4)Cheapest credible option; check your data policyYesYes
n8nOrchestrating export → generate → validate → import without writing a servicen/aYes
Shopify MagicOne-off fixes, new-product draftsNoNo
Amazon listing AIMarketplace listings inside Seller CentralNoPartially

Claude Haiku 4.5 is the right default for bulk. This is not a reasoning task — it is constrained rewriting against a schema. Haiku is the cheapest model in Anthropic's lineup at $1 per million input tokens and $5 per million output, it supports schema-guaranteed structured outputs, and the Batch API halves both. Spending Opus-class money to rephrase a spec sheet turns a $1 job into a $7–$14 one for no measurable gain.

Use a larger model — Claude Sonnet 5, GPT-5.5 — for two things only: writing the three or four gold-standard examples you put in the prompt, and categories where the copy carries the sale. One cost trap: Sonnet 5's newer tokenizer produces roughly 30% more tokens for the same text, so multiply its headline price by about 1.3 to get the real one. Under the introductory pricing that runs to 31 August 2026 it is 2x Haiku on paper and ~2.6x in practice; from 1 September it becomes 3x on paper and ~3.9x in practice.

What the platforms actually require

Every "AI product descriptions" post gets this wrong, in both directions.

Google Search does not penalize AI-generated content for being AI-generated. Its guidance judges content on quality. What it does police is scaled content abuse: using generative AI "to generate many pages without adding value for users." Descriptions that make a spec table legible add value. Descriptions that pad one with adjectives are what that policy was written for.

Google Merchant Center has a hard provenance rule. AI-generated titles and descriptions are permitted, but must be submitted through the structured_title and structured_description attributes, each carrying a digital_source_type sub-attribute set to trained_algorithmic_media. Note the asymmetry: supply both description and structured_description and Google prioritizes the plain one — the structured attribute declares provenance, it does not override.

Amazon's position is about accuracy, not authorship. Amazon builds its own generative listing tools and reports that more than 900,000 selling partners have used them, that sellers accept the output with little or no editing about 90% of the time, and that such listings show a 40% lift in "overall listing quality." Read those for what they are: Amazon's metrics, about Amazon's tool, on a scale Amazon defines. The real signal is that the largest marketplace on earth is actively pushing sellers toward AI-written listings — nobody is going to disapprove yours for being one.

The duplicate-content penalty is a myth, and the real risk is worse. Google has said repeatedly there is no penalty for duplicate product descriptions, manufacturer-supplied ones included. What happens instead is consolidation: Google picks one page among near-identical ones and drops the rest. For a catalog that is 500 pages competing to be the one Google keeps — which is why the deduplication step exists.

Step-by-Step Implementation

1. Export the feed and audit your attributes before writing a single prompt

In Shopify: Products → Export → CSV. In WooCommerce: Products → Export. That file is the only input the model will ever see.

Before prompting anything, count coverage. For each attribute you care about — material, dimensions, weight, care instructions, origin, compatibility, what is in the box — what fraction of your 500 rows actually has it?

This is the highest-leverage hour in the project and the one everybody skips. A model given a thin row does not write a thin description. It writes a rich, fluent, invented one. If material is empty in 40% of your rows, you are about to generate 200 descriptions with a made-up material in them.

Fix the data or accept the omission. "The model will figure it out" is not a third option — it is the first failure mode.

2. Define the JSON schema — this is the contract

The schema is the whole reason bulk generation works. It forces the output into the exact fields your import file needs, and the API enforces it by constraining decoding, so you cannot get back something unparseable.

Product Description Schema (Claude structured outputs)
{
  "model": "claude-haiku-4-5",
  "max_tokens": 1500,
  "system": "<the system prompt from step 3>",
  "messages": [
    { "role": "user", "content": "<the SKU's attribute row as key: value lines>" }
  ],
  "output_config": {
    "format": {
      "type": "json_schema",
      "schema": {
        "type": "object",
        "properties": {
          "sku": { "type": "string" },
          "template_id": {
            "type": "string",
            "enum": ["problem_first", "sensory_first", "spec_first",
                     "use_case_first", "provenance_first", "comparison_first"]
          },
          "title": { "type": "string" },
          "short_description": { "type": "string" },
          "bullets": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "text": { "type": "string" },
                "source_attribute": { "type": "string" }
              },
              "required": ["text", "source_attribute"],
              "additionalProperties": false
            }
          },
          "long_description": { "type": "string" },
          "meta_description": { "type": "string" },
          "omitted_because_unknown": {
            "type": "array",
            "items": { "type": "string" }
          }
        },
        "required": ["sku", "template_id", "title", "short_description",
                     "bullets", "long_description", "meta_description",
                     "omitted_because_unknown"],
        "additionalProperties": false
      }
    }
  }
}

The full API request body. Note what the schema does NOT do: Anthropic's structured outputs do not support JSON Schema length constraints such as maxLength, so on Claude character limits must be enforced in your own code. (Gemini and OpenAI do support them.) That surprises people, and it is why step 5 exists.

Three decisions in there are doing real work:

bullets is an array of objects, not strings. Every bullet must name the source_attribute it came from. A bullet citing material when the row has no material field is a hallucination your validator catches mechanically. That single change converts "hope the model didn't make things up" into a test that passes or fails.

omitted_because_unknown forces the model to declare its gaps. Models fill silence. Give them a legitimate place to put "I don't know the care instructions" and they are markedly less likely to invent them — and you get a ranked list of which attributes to go collect.

template_id is how you fight sameness (step 6).

Note the limitation, and note whose it is. Anthropic's structured outputs do not support minLength, maxLength or numeric bounds — so on Claude, the schema cannot enforce "meta description under 160 characters." (Anthropic's official SDKs soften this: they strip the unsupported keywords, fold them into the field description, and validate the response against your original schema client-side.) This is not universal. Gemini's schema object accepts minLength/maxLength/pattern; OpenAI supports numeric bounds plus pattern and format, so a length rule is enforceable there via regex.

Build on Claude, as this guide does, and you enforce length in code. Either way: ask in the prompt, check in code — which is why every serious pipeline has a repair pass.

3. Write the system prompt once, reuse it 500 times

Bulk Description System Prompt

You write product copy for [BRAND], a [CATEGORY] retailer selling to [AUDIENCE].

The grounding rule — this overrides everything else below. You may only state facts that appear in the attribute row you are given. If an attribute is absent, you do not have it, and you may not infer it from the product name, the price, the category, or from products like it. Every bullet must name the exact attribute key it came from in source_attribute. Any attribute a shopper would reasonably want and that you do not have goes in omitted_because_unknown.

You may NEVER assert any of the following unless the row states it explicitly: waterproof, water-resistant, hypoallergenic, non-toxic, BPA-free, food-safe, dishwasher-safe, machine-washable, organic, recycled, antimicrobial, flame-retardant, lifetime warranty, or any medical, safety or certification claim.

Voice. [2-3 sentences of brand voice. Be specific: "plain, declarative, no exclamation marks, second person, never call the product 'stunning'."]

Banned phrases. Do not use: elevate, elevated, whether you're, look no further, game-changer, must-have, crafted with care, boasts, in today's fast-paced world, perfect for those who, take your [X] to the next level, unparalleled, seamlessly.

Structure. You will be told which template_id to use. Obey it:

  • problem_first — open with the problem this product solves
  • sensory_first — open with how it looks, feels or sounds in use
  • spec_first — open with the single most important specification
  • use_case_first — open with a concrete moment of use
  • provenance_first — open with where or how it was made
  • comparison_first — open with what it is instead of

Length targets (approximate; they are checked downstream, so stay comfortably inside):

  • title: under 140 characters
  • short_description: 1 sentence, under 200 characters
  • bullets: 3 to 5, each under 120 characters
  • long_description: 120-180 words
  • meta_description: under 150 characters

Gold-standard examples of the voice: [PASTE 3 DESCRIPTIONS YOU ACTUALLY LIKE — ideally human-written, from your own site. This is worth more than any other instruction here.]

This is the shared prefix — the same ~1,500 tokens on every one of the 500 calls. The per-SKU user message is just the attribute row. Replace the brand-voice and banned-phrase blocks with your own.

The banned-phrase list is not fussiness. It is the cheapest intervention against the sameness problem, because those are precisely the phrases a model reaches for when it has nothing specific to say.

4. Run the batch

Assign each SKU a template_id deterministically — templates[hash(sku) % 6] — so the rotation is stable across reruns and any row is reproducible. Then submit all 500 as one batch job rather than 500 live calls: half the price, no rate limits, and one artifact you can re-download instead of a fragile loop.

For a no-code path, n8n will read the CSV, call the API per row, run the checks and write the output file — on a schedule, for new products.

5. Machine-validate all 500 — this is the gate, not the spot-check

Every one of these runs on 100% of the output, in seconds, before a human reads anything:

  • Schema validity — free, guaranteed by structured outputs. If it is not free, your pipeline is not using them.
  • Length limits — the ones the schema could not enforce. Merchant Center caps title at 150 characters and description at 5,000. The familiar ~160-character meta description limit is a working heuristic, not a Google spec — Google publishes no length limit and truncates snippets to fit the device.
  • Attribute grounding — for every bullet, assert that source_attribute is a key that exists and is non-empty in that SKU's row. This is the check that catches invented features, and it is about six lines of code.
  • Number grounding — every digit sequence in the output must appear in the input row. Catches invented dimensions, weights, capacities and warranty terms.
  • Forbidden-claim regex — the safety and certification words from the system prompt, as a hard fail rather than a hope.
  • Banned-phrase regex for voice drift, and near-duplicate detection (step 6).

Anything that fails gets a repair pass: send the output back with the specific failure ("meta_description is 178 characters, must be under 150") and regenerate that field only. Repair passes typically touch 5–15% of rows and cost almost nothing.

6. Deduplicate — the failure everyone discovers three months late

Run 500 near-identical prompts through one model and you get 500 outputs that share a skeleton. Not copies — convergent. Same rhythm, same three-beat sentences, same opening move. Humans register it as "this site's copy is weirdly samey." Google registers it as pages so alike it need only index one.

Measure it before you ship:

  1. Count trigrams across all 500 descriptions and print the top 20. If perfect for those appears in 380 of 500, you have found the problem in ten seconds. It is the most useful diagnostic in the pipeline and almost nobody runs it.
  2. Check opening uniqueness. The first eight words of every description should be unique across the catalog. Duplicate openings are the most visible form of sameness.
  3. Pairwise near-duplicate score. Shingle each long_description into 5-grams and compute Jaccard similarity between pairs (MinHash if 500 becomes 50,000). Flag any pair above ~0.3 that is not a genuine variant.

The fixes, in order of effect: the template_id rotation, the banned-phrase list, and — the big one — feeding rows that actually differ. Convergence is usually a data symptom. Two products whose rows differ only in colour produce two descriptions that differ only in colour, and no prompt fixes that.

7. Spot-check with statistics, because you cannot read 500

You do not need to read 500. You need to know your defect rate.

Draw a random sample — not the first 20, not your favourites — and read it against the source row. The arithmetic for how many: read 60 randomly chosen descriptions, find zero defects, and the rule of three puts the 95% upper bound on your true defect rate at 3/60 = 5%. On 500 SKUs that still means up to 25 bad descriptions are live.

Which is the whole argument for step 5. Sampling alone cannot get the defect rate low enough, so the machine checks have to catch the errors that matter — false claims — on 100% of rows, leaving sampling to catch style.

Then read 100% of one group: your top 20 SKUs by revenue, plus anything returns-heavy or regulated. The head of a catalog is short. Read it.

8. Import in draft, with a rollback

Shopify's product CSV import matches on the Handle column; WooCommerce's matches on ID or SKU. Both will happily overwrite 500 live product pages with a bad run.

  • Import to a staging store or draft status first, and look at ten rendered pages. Fields that survive a CSV round-trip still break in a theme.
  • Keep the pre-run export. That file is your rollback.
  • Write a run_id into a product metafield, so you can tell later which descriptions came from which run and prompt version.
  • Prefer the Admin API over CSV on a live catalog — CSV import has a habit of clearing fields you left blank.

9. Declare provenance in your feed

If these go to Google Shopping, submit them in structured_description with digital_source_type: trained_algorithmic_media. One extra column, and it is Merchant Center's own stated requirement.

Real-World Examples

Example 1: The thin row invents a product

Input row (what most catalogs actually contain):

sku: JK-4471
title: Men's Jacket
category: Outerwear
price: 189.00

Output (Haiku 4.5, good prompt, thin row):

Crafted from premium water-resistant fabric, this versatile men's jacket features a durable YKK zipper, a soft fleece-lined interior, and three spacious pockets to keep your essentials secure. Machine washable and built to last through seasons of wear.

Fluent, on-brand, and entirely fabricated. Water-resistant, YKK, fleece-lined, three pockets, machine-washable: not one appears in the row. Two of them are objective product claims that will produce returns and that you would have to substantiate if anyone asked.

Input row (same SKU, after the step-1 attribute audit):

sku: JK-4471
name: Fieldstone Waxed Cotton Jacket
material: 100% waxed cotton, 8oz; cotton twill lining
water_resistance: water-repellent; NOT waterproof
pockets: 2 hand, 1 internal chest
closure: brass snap front
care: wipe clean; re-wax annually; do not machine wash
origin: made in Portugal
price: 189.00

Output (same model, same prompt, template_id: provenance_first):

Made in Portugal from 8oz waxed cotton, with a cotton twill lining and a brass snap front. The wax finish sheds a light shower — it is water-repellent, not waterproof, so it is a jacket for a grey morning rather than a downpour. Two hand pockets, one internal chest pocket. Wipe it clean rather than washing it, and re-wax it once a year; done that way it outlasts anything you can put in a machine.

omitted_because_unknown: ["fit", "weight", "size_range"]

What changed: nothing about the model or the prompt. Only the input row. The second description is more specific, more useful, and makes zero claims you cannot defend. The clause "water-repellent, not waterproof" is the most valuable thing on the page: it is version one's returns liability, converted into a trust signal. And omitted_because_unknown just handed you the merchandising to-do list for this SKU.

Example 2: Five hundred descriptions with one voice

Before. First full run, 500 SKUs, no template rotation and no banned-phrase list. Top trigrams across the corpus:

"perfect for those"        381 / 500
"whether you're"           344 / 500
"elevate your"             290 / 500
"crafted from premium"     271 / 500
"look no further"          166 / 500

Three of the first five descriptions opened with the identical construction:

"Elevate your everyday with…" "Elevate your workspace with…" "Elevate your morning routine with…"

No individual description is bad. The catalog is unreadable.

After. Same model, same rows. Added: the deterministic six-way template_id rotation and the banned-phrase list. Rerun:

"perfect for those"          0 / 500
"whether you're"             0 / 500
"made in"                   47 / 500
"designed for"              31 / 500

Openings, now varied by template:

(spec_first)"8oz waxed cotton, which is heavy enough that…" (problem_first)"Most desk lamps put the light where the lamp is, not where you are." (use_case_first)"You will reach for this at 6am, in the dark, half-awake."

What changed: two paragraphs in the system prompt and one line of hashing code. Duplicate 5-gram pairs above 0.3 similarity fell from 88 to 4 — and all four survivors were genuine colourway variants of the same product, which should read alike.

Example 3: The check the schema cannot do

The schema guarantees meta_description is a string. On Claude it cannot guarantee the string is short — Anthropic's structured outputs do not support maxLength.

Generated: a 178-character meta description, perfectly valid against the schema. Google truncates at roughly 160, cutting the call to action off mid-word on a page you are paying to rank. Caught by: one line, len(out["meta_description"]) > 155, which flagged 63 of 500 rows. Repaired by: a second call quoting the failure back, regenerating that field only, for a fraction of a cent. Cost of not having the check: 63 truncated snippets nobody notices for a year.

Industry-Specific Applications

Apparel and footwear. The highest hallucination risk in retail: fabric, care and fit claims are what a model invents and what drives returns. Never let it near a fibre composition that is not in the row.

Consumer electronics. Rows are rich, so grounding is easy — but "compatible with all iPhone models," invented once across 200 accessory SKUs, is 200 wrong pages. Make compatibility verbatim-only.

Food, supplements and cosmetics. Not without a reviewer who has regulatory sign-off. The forbidden-claim regex is a safety net, not a compliance function.

Resellers of manufacturer copy. The clearest win — you are competing against every retailer showing byte-identical manufacturer text. A grounded rewrite gives Google a reason to index your page.

Best Practices

  • Audit attribute coverage before you write a prompt. Thin rows do not produce thin copy; they produce invented copy.
  • Force a JSON schema. Always. Free prose does not map to fields, and parsing it back is a bug factory.
  • Make every bullet cite its source attribute. The difference between hoping and testing.
  • Give the model somewhere to put "I don't know." omitted_because_unknown reduces invention and produces your data to-do list for free.
  • Use the cheap model. Constrained rewriting, not reasoning. Save the frontier model for the gold-standard examples.
  • Batch, don't loop. Half price, no rate limits, one reproducible artifact.
  • Machine-check 100%; human-check a random sample and the whole head of the catalog.
  • Count your trigrams. Ten seconds, and it tells you more than reading twenty descriptions would.

Common Pitfalls

The confident invented attribute. The defining failure of this workflow. Handed a sparse row, a model does not hedge — it produces a specific, plausible, false claim. "Waterproof" on a jacket that is merely water-repellent is a return, a chargeback, and an unsubstantiated objective product claim that consumer-protection regimes take seriously. "The model wrote it" has never been a defence in advertising law and will not become one. See hallucinations.

Assuming a JSON schema prevents lying. Structured outputs guarantee the shape, not the truth. A schema-valid description can be entirely fictional. Grounding is a separate mechanism and you have to build it.

Assuming the schema enforces your length limits. On Claude it cannot — Anthropic does not support maxLength. Check your provider's supported keywords before you rely on one; on Claude, ask in the prompt, verify in code, repair.

Convergent sameness, discovered late. Five hundred descriptions that all sound alike is not a stylistic complaint; it is an indexing problem and a brand problem. It does not show up in a spot check of ten, because each of the ten reads fine. It appears only when you count.

Importing straight to live. A CSV import that clears a field you left blank will do it to 500 products at once, at 4pm on a Friday.

Measuring Success

Defect rate, measured properly. Random sample, read against the source row, count factual errors. Sixty read with zero defects buys 95% confidence that the true rate is under 5%. Report that, not "the descriptions look good."

Grounding-check pass rate. The share of bullets whose source_attribute resolves to a non-empty field. Should be 100% after repair. If the first pass is below ~90%, the problem is your data, not your prompt.

Trigram concentration. Frequency of your most common three-word phrase across the catalog. If any trigram appears in more than ~10% of descriptions, look at it.

Indexation. In Search Console, product pages indexed versus submitted, before and after. Consolidation of near-identical pages shows up here — the metric that connects deduplication to money.

Returns coded "not as described." The slowest indicator, and the one that matters most. Watch it on the SKUs you regenerated; a rise means the grounding gate leaked.

Cost Analysis

Assumptions, stated so you can substitute your own: ~1,800 input tokens per SKU (a ~1,500-token shared prefix — system prompt, schema, banned phrases, gold examples — plus a ~300-token attribute row) and ~500 output tokens (title, short description, five bullets, a 150-word long description, a meta description, JSON overhead).

ModelRate (per 1M in/out)Per SKU500 SKUs
DeepSeek V4 (flash)$0.14 / $0.28~$0.0004~$0.20
Claude Haiku 4.5, Batch API$0.50 / $2.50~$0.0022~$1.08
Gemini 3.5 Flash, batch$0.75 / $4.50~$0.0036~$1.80
Claude Haiku 4.5, standard$1 / $5~$0.0043~$2.15
Claude Sonnet 5, batch (intro)$1 / $5~$0.0056~$2.80
GPT-5.5, standard$5 / $30~$0.024~$12.00

Worked, for the recommended default. Claude Haiku 4.5 is $1 per million input tokens and $5 per million output; the Batch API discounts both by 50%, giving $0.50 and $2.50.

  • Input: 1,800 × $0.50 / 1,000,000 = $0.0009
  • Output: 500 × $2.50 / 1,000,000 = $0.00125
  • Per SKU: $0.00215 → 500 SKUs: $1.08

Add a 15% repair pass and it is about $1.20. Do not budget for prompt caching on top: Haiku 4.5's minimum cacheable prefix is 4,096 tokens, and the shared prefix here is nowhere near that — it silently caches nothing, with no error. Caching also does not reliably hit inside a batch. (The Sonnet 5 row already accounts for its tokenizer producing ~30% more tokens on the same text; without that adjustment you would under-budget it.)

Now the number that matters. Published freelance-rate guides put e-commerce copywriting at $0.10–$0.25 per word entry-level and $0.50–$1.00 for experienced writers — get your own quote rather than trusting mine. At the cheapest end a 150-word description is $15, so 500 is $7,500. Which makes the naive comparison $1.08 against $7,500 — not the interesting one.

The real comparison is review time. Someone reads a sample, fixes failures, signs off on the head of the catalog:

  • 60-description random sample, ~3 minutes each: 3 hours
  • Top 20 SKUs read in full against source rows: 1.5 hours
  • Repair review and re-import: 1.5 hours
  • ~6 hours. At a $50/hour internal cost, $300 — roughly 280x the token bill.

Which tells you where to optimise: not the model. Every hour spent on the attribute audit and the machine gates removes review hours, and review hours are the budget. A pipeline with no grounding check does not save you $1; it costs you the fifteen hours you will spend reading all 500 descriptions because you cannot trust any of them.

Set-up is one to two days for the first run, mostly the attribute audit and the validator — then under an hour per run, which is what makes this worth building rather than clicking through Shopify Magic 500 times.

  • Claude — the generation engine; schema-guaranteed structured outputs, 50% Batch API discount
  • ChatGPT — capable alternative, meaningfully more expensive per SKU at flagship tier
  • Google Gemini — strong price/quality; good when attributes must be read from product images
  • DeepSeek — cheapest credible option; check your data-handling policy first
  • n8n — orchestrates export → generate → validate → import without a bespoke service
  • Perplexity AI — filling attribute gaps from manufacturer sources before you generate
  • Claude Haiku 4.5 — the default for bulk: $1/$5 per million tokens, halved again in batch
  • Claude Sonnet 5 — for the gold-standard examples and copy-led categories
  • Gemini 3.5 — competitive batch pricing, strong multimodal attribute extraction
  • GPT-5.5 — capable flagship; price it per SKU before committing a catalog to it
  • DeepSeek V4 — cheapest per SKU by a wide margin

If the schema part is new to you, the mechanism is the one behind function calling: output constrained to a shape you defined, which is what makes it safe to pipe into another system. And if your first run produces confident nonsense, the concept you need is hallucinations — not a bug in the model, but what a model does when your data has a hole in it.

Frequently Asked Questions

No. Google Search's published guidance is that content is judged on quality, not on how it was produced — but using generative AI to spin up many pages that add nothing for users falls under its scaled content abuse spam policy. Google Merchant Center is stricter about provenance: AI-generated titles and descriptions are allowed, but they must be submitted in the structured_title and structured_description attributes with digital_source_type set to trained_algorithmic_media.
About a dollar in tokens. At roughly 1,800 input and 500 output tokens per SKU, Claude Haiku 4.5 through the Batch API (50% off list, so $0.50 and $2.50 per million tokens) works out to about $0.0022 per SKU, or $1.08 for 500. The real cost is human review time, which is hundreds of times larger.
No. Shopify Magic is free across all plans, but it generates one description at a time from inside a single product's admin page. There is no native bulk generation mode. For a whole catalog you need to export the product CSV, generate against an API, and import the results back.
Yes — Amazon builds and promotes its own generative listing tools, and says more than 900,000 selling partners have used them. Amazon's rule is about accuracy, not provenance: the listing must accurately represent the physical product, and that obligation stays with the seller regardless of what wrote the text.
Because the model is receiving nearly the same prompt 500 times and converges on its highest-probability phrasing. The fixes are structural: rotate a fixed set of opening templates deterministically by SKU, ban the phrases the model reaches for by default, and feed genuinely differentiating attributes rather than thin rows. Then measure it — count the most common trigrams across your 500 outputs and look at the top of the list.
Yes, and confidently. Given a thin attribute row, a model will fill the gap — it will decide a jacket is waterproof, a bowl is dishwasher-safe, or a fabric is hypoallergenic. Every one of those is a return, and an unsubstantiated objective product claim is a consumer-protection problem in most jurisdictions. Make the model cite the source attribute for every claim, then reject in code any claim that is not in the input row.
In Google Merchant Center, yes — that is what the digital_source_type sub-attribute is for. In Google Search there is no disclosure requirement, only a quality bar. Amazon's published seller guidance is less explicit than Google's, and secondary sources disagree on whether disclosure is required, so check your current Seller Central policy pages rather than trusting a blog post.

Explore More Use Cases

Discover other AI use cases and practical applications.