HomeShopify & E-commerceShopify Google Shopping product feed with…

Shopify Google Shopping product feed with n8n

Shopify Google Shopping product feed with n8n











A Shopify Google Shopping product feed built in n8n pulls every product and variant from your store on a schedule and writes them into a Google Sheet formatted as a Merchant Center feed, so your catalog shows up in free Google Shopping listings without a paid app. This guide builds the four-node workflow from scratch, explains each field Google requires, and hands you a ready-to-import template if you would rather skip the wiring and be live in about ten minutes.

What it does

The workflow runs on a schedule, reads your full Shopify catalog, reshapes it into the exact columns Google Merchant Center expects, and keeps a Google Sheet in sync as your feed source. Merchant Center then pulls that sheet on its own fetch schedule, and your products appear in the free Google Shopping tab and in the Shopping listings across Search.

Here is the shape of it end to end:

  Schedule (daily)
        |
        v
  Shopify: get all products  ---> [ {product, variants[], images[]}, ... ]
        |
        v
  Code: build feed rows      ---> one row PER VARIANT
        |                          id, title, description, link,
        |                          image_link, price, availability...
        v
  Google Sheets (appendOrUpdate on id)  ===>  Merchant Center reads this sheet
  

Because the sheet is the single source of truth, you never re-upload a file. n8n keeps the rows current, Merchant Center reads them on schedule, and your listings follow along. This is one of the highest-leverage jobs in the whole n8n Shopify automation toolkit: free traffic, set up once.

Why it beats the default

Shopify’s own Google channel and most feed apps work, but they hide the mapping. You get whatever title and description they decide to send, limited rules, and in the case of many third-party apps a monthly fee that scales with your catalog size. A feed you own in a Google Sheet flips all of that.

  • Full control over how title and description are built, including stripping HTML and appending variant names.
  • No per-product app pricing. The whole stack (n8n self-hosted, Shopify API, Google Sheets, Merchant Center) is free at the volumes most stores run.
  • The feed is plain data in a sheet you can open, audit, and fix by hand if Google flags a row.
  • You decide which products are included: filter drafts, hidden collections, or zero-price items before they ever reach Google.

What you need

  • An n8n instance, cloud or self-hosted.
  • A Shopify store and an Admin API access token. If you have not connected Shopify to n8n yet, follow connect Shopify to n8n (2026) first, using the Dev Dashboard method.
  • A Google account with Google Sheets OAuth set up in n8n.
  • A free Google Merchant Center account.
  • About 30 minutes to build from scratch, or under 10 with the template.

Node-by-node list

# Node Type Job
1 Every morning scheduleTrigger Fires the workflow once a day at 4am.
2 Get all products shopify Returns every product with its variants and images.
3 Build feed rows code Flattens products into one Merchant-format row per variant.
4 Write feed sheet googleSheets Append-or-update each row in the feed sheet, matched on id.

Step-by-step build

1 Every morning (Schedule Trigger)

Add a Schedule Trigger. Set the rule to trigger every day at hour 4. This is your feed refresh cadence; you will line it up with the Merchant Center fetch time in the last step.

💡

If prices or stock swing during the day, add a second interval (for example hour 4 and hour 16) so the sheet is fresh twice a day.

2 Get all products (Shopify)

Add a Shopify node. Set Resource to Product, Operation to Get Many, and turn on Return All so pagination is handled for you. Attach your Shopify credential. Each item that leaves this node is one product, with a variants array and an images array inside it.

{
  "id": 8123456789,
  "title": "Ceramic Pour-Over Kettle",
  "handle": "ceramic-pour-over-kettle",
  "vendor": "Northwind Coffee",
  "body_html": "<p>A slow-pour kettle for even extraction.</p>",
  "images": [{ "id": 111, "src": "https://cdn.shopify.com/.../kettle.jpg" }],
  "variants": [
    { "id": 45001, "title": "Matte White", "price": "48.00", "sku": "KET-WHT",
      "barcode": "0810000000015", "inventory_quantity": 12,
      "inventory_management": "shopify", "inventory_policy": "deny", "image_id": 111 }
  ]
}

3 Build feed rows (Code)

Add a Code node and paste the script below. It loops every product, then every variant inside it, and emits one clean row per variant with the attribute names Merchant Center expects. Set STORE_DOMAIN to your storefront domain so the link column points at the right product page.

const STORE_DOMAIN = 'your-store.myshopify.com';
const CURRENCY = 'USD';

const rows = [];

for (const item of $input.all()) {
  const p = item.json;
  const handle = p.handle;
  const vendor = p.vendor || '';
  const description = (p.body_html || '')
    .replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim().slice(0, 5000);
  const firstImage = (p.images && p.images[0] && p.images[0].src)
    || (p.image && p.image.src) || '';

  for (const v of (p.variants || [])) {
    let imageLink = firstImage;
    if (v.image_id && p.images) {
      const match = p.images.find(img => img.id === v.image_id);
      if (match) imageLink = match.src;
    }
    const tracked = v.inventory_management === 'shopify';
    const inStock = !tracked || v.inventory_quantity > 0 || v.inventory_policy === 'continue';

    rows.push({ json: {
      id: String(v.id),
      item_group_id: String(p.id),
      title: p.title + (v.title && v.title !== 'Default Title' ? ' - ' + v.title : ''),
      description,
      link: `https://${STORE_DOMAIN}/products/${handle}?variant=${v.id}`,
      image_link: imageLink,
      availability: inStock ? 'in_stock' : 'out_of_stock',
      price: `${v.price} ${CURRENCY}`,
      condition: 'new',
      brand: vendor,
      mpn: v.sku || String(v.id),
      gtin: v.barcode || ''
    }});
  }
}

return rows;

After this node, a single variant looks like a finished feed row:

{
  "id": "45001",
  "item_group_id": "8123456789",
  "title": "Ceramic Pour-Over Kettle - Matte White",
  "description": "A slow-pour kettle for even extraction.",
  "link": "https://your-store.myshopify.com/products/ceramic-pour-over-kettle?variant=45001",
  "image_link": "https://cdn.shopify.com/.../kettle.jpg",
  "availability": "in_stock",
  "price": "48.00 USD",
  "condition": "new",
  "brand": "Northwind Coffee",
  "mpn": "KET-WHT",
  "gtin": "0810000000015"
}

4 Write feed sheet (Google Sheets)

Create a Google Sheet with a header row whose columns exactly match the keys above: id, item_group_id, title, description, link, image_link, availability, price, condition, brand, mpn, gtin. Then add a Google Sheets node:

  1. Operation: Append or Update Row.
  2. Document: pick your feed spreadsheet.
  3. Sheet: pick the tab (the template targets gid=0).
  4. Mapping: Map Automatically, and set the column to match on to id.

Append-or-update on id means a variant that already exists is overwritten in place instead of duplicated, so the sheet stays clean run after run.

5 Point Merchant Center at the sheet

In Google Merchant Center, go to Products, add a primary feed, choose Google Sheets as the source, select this spreadsheet, and set a fetch schedule an hour or so after your n8n run. Save and activate the workflow in n8n. From then on, n8n refreshes the sheet each morning and Merchant Center reads it shortly after.

Common mistakes

  • Sending one row per product instead of per variant. Sizes and colors are separate offers; skip the variant loop and half your catalog goes missing.
  • Price without a currency. Google needs 48.00 USD, not 48.00. The Code node appends the currency for you, so keep that format.
  • Sheet headers that do not match the attribute names. image_link spelled image, or a stray capital letter, and Google ignores the column.
  • Using Append instead of Append or Update. Plain append stacks a fresh copy of every variant on each run and the feed balloons with duplicates.
  • Missing images. Offers with no image_link are disapproved, so the fallback to the first product image matters; make sure every product has at least one image in Shopify.
  • Forgetting item_group_id. Without it, Google treats each variant as an unrelated product instead of grouping them under one listing.

Cost at realistic volume

This workflow is effectively free to run. Self-hosted n8n has no per-execution charge; on n8n Cloud one scheduled run per day is a rounding error against any plan. The Shopify Admin API is free to read from. Google Sheets and Google Merchant Center are both free.

Catalog size Rows written / day Monthly cost
200 products (~500 variants) ~500 $0
1,000 products (~2,500 variants) ~2,500 $0
5,000 products (~12,000 variants) ~12,000 $0 (well inside Sheets limits)

Compare that with feed apps that commonly charge a monthly fee per active product count, and the case for owning the feed is easy to make.

Ready-to-import template

The full guide above is free to follow. If you would rather not wire four nodes and format a sheet by hand, the ready-to-import template drops the exact workflow into n8n in a couple of clicks. Add your Shopify and Google credentials, set your store domain, and your feed is live. Want it done for you end to end? See our done-for-you setup service.

Download the template ($13) →

Instant download · Works on n8n Cloud and self-hosted

Frequently asked questions

Can Google Merchant Center read a Google Sheet as a product feed?

Yes. In Merchant Center you add a primary feed with Google Sheets as the source, then set a fetch schedule. Merchant Center reads the sheet on that schedule, so keeping the sheet current with n8n keeps your listings current. No paid app or file host is needed.

Do I need one row per product or one row per variant?

One row per variant. Each purchasable variant is a distinct offer with its own id, price, and availability. The workflow flattens every product into its variants and links them with item_group_id so Google groups sizes and colors under one product.

Will this replace the Shopify Google and YouTube channel app?

It can. The n8n feed gives you full control over titles, descriptions, and which products are included, with no app in the middle. Some merchants run both: the app for conversion tracking and the sheet feed for catalog control. Choose based on how much mapping control you want.

How often should the feed refresh?

A daily run matched to your Merchant Center fetch schedule is enough for most stores. If prices or stock change through the day, run it every few hours. Merchant Center still only reads on its own fetch schedule, so match the two so they line up.

What if a product has no images or is out of stock?

Google disapproves offers with no image_link, so the Code node falls back to the first product image. Out-of-stock variants stay in the feed with availability set to out_of_stock, which is correct: Google prefers a stable feed over rows that vanish and reappear.

Related guides

n8n
Shopify
Google Sheets
Google Merchant Center
automation