Shopify to Google Sheets, product lists always current
Your product sheet is never quite right. Someone exported a CSV last week, variants changed yesterday, and now you’re planning a promo on numbers you don’t fully trust. It’s the kind of small mess that quietly creates bigger ones.
Ecommerce managers feel it first, because they live inside price lists and inventory checks. But marketing leads building campaigns and agency owners reporting on catalogs run into the same wall. This Shopify Sheets sync keeps your Google Sheet current automatically, so planning doesn’t depend on “who exported it last.”
Below you’ll see how the workflow pulls products from Shopify, writes clean rows into Google Sheets, and keeps going even when you have a big catalog with lots of pages.
How This Automation Works
See how this solves the problem:
n8n Workflow Template: Shopify to Google Sheets, product lists always current
flowchart LR
subgraph sg0["Schedule Flow"]
direction LR
n0@{ icon: "mdi:cog", form: "rounded", label: "Wait1", pos: "b", h: 48 }
n1@{ icon: "mdi:cog", form: "rounded", label: "No Operation, do nothing", pos: "b", h: 48 }
n2["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/graphql.png' width='40' height='40' /></div><br/>Shopify get products"]
n3["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Split output"]
n4@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Check if there is next page", pos: "b", h: 48 }
n5@{ icon: "mdi:database", form: "rounded", label: "writing first product details", pos: "b", h: 48 }
n6@{ icon: "mdi:swap-vertical", form: "rounded", label: "Set cursor", pos: "b", h: 48 }
n7@{ icon: "mdi:database", form: "rounded", label: "writing remaning product inf..", pos: "b", h: 48 }
n8@{ icon: "mdi:play-circle", form: "rounded", label: "Schedule Trigger", pos: "b", h: 48 }
n9@{ icon: "mdi:database", form: "rounded", label: "update Curser", pos: "b", h: 48 }
n10@{ icon: "mdi:swap-horizontal", form: "rounded", label: "If", pos: "b", h: 48 }
n11["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Code"]
n12@{ icon: "mdi:swap-vertical", form: "rounded", label: "BatchSize", pos: "b", h: 48 }
n13@{ icon: "mdi:database", form: "rounded", label: "LastCursor", pos: "b", h: 48 }
n14["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/graphql.png' width='40' height='40' /></div><br/>shopify-initial"]
n15@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Check cursor is not empty", pos: "b", h: 48 }
n10 --> n14
n10 --> n11
n11 --> n2
n0 --> n6
n12 --> n13
n13 --> n10
n6 --> n2
n3 --> n7
n14 --> n5
n8 --> n12
n2 --> n3
n2 --> n15
n15 --> n9
n4 --> n1
n4 --> n0
n5 --> n11
n7 --> n4
end
%% Styling
classDef trigger fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef ai fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef aiModel fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px
classDef decision fill:#fff8e1,stroke:#f9a825,stroke-width:2px
classDef database fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef code fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef disabled stroke-dasharray: 5 5,opacity: 0.5
class n8 trigger
class n4,n10,n15 decision
class n5,n7,n9,n13 database
class n3,n11 code
classDef customIcon fill:none,stroke:none
class n2,n3,n11,n14 customIcon
The Challenge: Keeping product sheets accurate
Manual exports sound simple until you’re doing them constantly. A new variant gets added, a price changes for a weekend sale, tags get cleaned up for a collection page, and your “source of truth” spreadsheet instantly becomes yesterday’s news. Then you’re stuck cross-checking Shopify screens against rows, fixing mistakes one by one, and second-guessing every number in your report. Worse, spreadsheets tend to spread across a team. Once an old export is shared, it keeps getting reused.
It adds up fast. Here’s where it usually breaks down.
- You end up exporting CSVs repeatedly, and it’s never at the right moment.
- Variant-level details (like SKUs, prices, and inventory) get missed or pasted into the wrong columns.
- Large catalogs become a chore because exports, filters, and “did we grab everything?” checks take forever.
- Teams make decisions from stale sheets, which means promos, ads, and merchandising plans drift off reality.
The Fix: Shopify product data synced into Google Sheets
This workflow runs on a schedule (hourly, daily, whatever you choose) and pulls your Shopify product data using GraphQL. It doesn’t just grab a shallow list. It collects useful fields like product title, description, tags, variants, images, and inventory-related details so your sheet can support real work: promo planning, catalog audits, pricing reviews, and quick analysis. If you have a lot of products, it keeps going page by page using a cursor, so it doesn’t start over each run or time out halfway through. Finally, it writes the results into a dedicated Google Sheet tab, while storing cursor details in a second tab to keep the sync reliable over time.
The workflow starts with a scheduled trigger, checks the last saved cursor, then fetches the next batch of Shopify products. It formats the response into spreadsheet-ready rows and appends them in Google Sheets. If there are more pages to fetch, it waits briefly and continues until it’s done.
What Changes: Before vs. After
| What This Eliminates | Impact You’ll See |
|---|---|
|
|
Real-World Impact
Say you refresh a product sheet three times a week for pricing checks, collection work, and promo planning. A typical manual cycle is about 30 minutes to export, download, clean columns, and re-share (longer if variants get messy), which is roughly 1.5 hours a week. With this workflow, the “work” is picking a schedule and letting it run; the actual effort is closer to 5 minutes to review the sheet and spot issues. Over a month, that’s a few hours back, plus fewer “wait, is this the latest?” moments.
Requirements
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Shopify Admin access to generate API credentials
- Google Sheets to store products and cursor state
- Shopify Admin API access token (create an app in Shopify admin)
Skill level: Intermediate. You’ll connect Shopify + Google credentials and paste a GraphQL query, but you won’t be writing a full app.
Need help implementing this? Talk to an automation expert (free 15-minute consultation).
The Workflow Flow
Scheduled run. A schedule trigger starts the sync on your cadence, like every morning or every hour during busy seasons.
Cursor check. Google Sheets is used not only for the product table, but also for a small “cursor” sheet that stores where the last run left off. If there’s no cursor yet, the workflow performs an initial Shopify fetch.
Fetch and format. Shopify is queried via GraphQL, the results are split into row-friendly structures, and fields are normalized so Google Sheets receives consistent columns (titles, tags, descriptions, prices, variants, images, inventory details).
Write and continue. The first row is appended, then the rest of the batch is appended. If Shopify indicates there are more pages, the workflow saves the next cursor, waits briefly, and repeats until the catalog is captured.
You can easily modify the schedule and the fields you store to match your reporting needs. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Scheduled Trigger
Set the workflow to run on a schedule and initialize the batch size used for pagination.
- Open Scheduled Run Trigger and set the schedule rule to run daily at
7(as shown in rule → interval → triggerAtHour). - Connect Scheduled Run Trigger to Set Batch Limit.
- In Set Batch Limit, set batchsize to
100using fields → values → numberValue. - Connect Set Batch Limit to Fetch Last Cursor to look up the prior pagination cursor.
Step 2: Connect Google Sheets
Set up Google Sheets nodes to read the last cursor, append product data, and update the cursor tracker sheet.
- Open Fetch Last Cursor and select the sheet named
Curserand the document ID[YOUR_ID]. - Credential Required: Connect your googleSheetsOAuth2Api credentials in Fetch Last Cursor.
- In Append First Product Row, set documentId to
[YOUR_ID]and sheetName togid=0(Sheet1). - Credential Required: Connect your googleSheetsOAuth2Api credentials in Append First Product Row, Append Product Rows, and Update Cursor Sheet.
- In Update Cursor Sheet, confirm operation is
updateand the tracker columns include tracker withcursorand endCursor as={{ $json.data.products.pageInfo.endCursor }}.
[YOUR_ID] placeholders with the actual Google Sheet IDs or the workflow will fail to write data.Step 3: Connect Shopify GraphQL
Configure the Shopify GraphQL nodes to fetch initial and paginated product data.
- Open Initial Shopify Fetch and set endpoint to
https://test-store-collection.myshopify.com/admin/api/2024-01/graphql.json. - Set the query in Initial Shopify Fetch to the provided GraphQL with
first: 1. - Credential Required: Connect your httpHeaderAuth credentials in Initial Shopify Fetch and Retrieve Shopify Items.
- In Retrieve Shopify Items, confirm endpoint is
https://test-store.myshopify.com/admin/api/2024-01/graphql.jsonand the query uses{{$json.batchsize}}and{{$json.endCursor}}.
Step 4: Set Up Cursor & Pagination Logic
Control pagination using the cursor, branch logic, and a delay between requests.
- Connect Fetch Last Cursor to Branch on Cursor and keep the condition
={{ $json.endCursor }}with the empty operator. - Route the “empty” branch to Initial Shopify Fetch and the other branch to Merge Cursor Data.
- In Merge Cursor Data, keep the provided JavaScript that merges outputs from Set Batch Limit, Fetch Last Cursor, and Initial Shopify Fetch.
- Configure Assign Next Cursor to set endCursor as
={{ $('Retrieve Shopify Items').item.json.data.products.pageInfo.endCursor }}and =batchsize as={{ $('Merge Cursor Data').item.json.batchsize }}. - Set Delay Interval to unit
secondsand amount10, then connect it to Assign Next Cursor to throttle pagination. - In Verify More Pages, keep the boolean condition
={{ $json.data.products.pageInfo.hasNextPage }}to branch to Delay Interval or finish at Idle Step.
Step 5: Configure Product Row Appends
Split Shopify results into individual items and append them to Google Sheets.
- In Divide Results, keep the Python code that iterates through
data.products.edgesand outputs one product per item. - Ensure Retrieve Shopify Items outputs to both Divide Results and Validate Cursor Present in parallel.
- In Append Product Rows, map columns using expressions like
={{ $json.data.product.title }},={{ $json.data.product.tags }}, and={{ $json.data.product.variants.edges[0].node.price }}. - In Append First Product Row, map fields using the first edge:
={{ $json.data.products.edges[0].node.title }}and similar fields for tags, price, and description. - Route Validate Cursor Present to Update Cursor Sheet to store
={{ $json.data.products.pageInfo.endCursor }}after each fetch.
Step 6: Test and Activate Your Workflow
Run the workflow end-to-end, confirm Sheets updates, then activate it for scheduled syncing.
- Manually execute Scheduled Run Trigger and confirm Set Batch Limit outputs a
batchsizeof100. - Verify that Retrieve Shopify Items runs and that Retrieve Shopify Items outputs to Divide Results and Validate Cursor Present in parallel.
- Check Google Sheets to confirm rows were added by Append First Product Row and Append Product Rows, and that Update Cursor Sheet wrote the latest cursor.
- When successful, toggle the workflow Active to allow scheduled runs at the configured hour.
Watch Out For
- Shopify credentials can expire or lack the right scopes. If it fails, check your custom app settings in Shopify Admin and confirm the Admin API permissions first.
- If you’re using Wait nodes or external rendering, processing times vary. Bump up the wait duration if downstream nodes fail on empty responses.
- Default prompts in AI nodes are generic. Add your brand voice early or you’ll be editing outputs forever.
Common Questions
Usually about an hour if you already have Shopify and Google access.
Yes, but someone needs to be comfortable with connecting credentials and copying a GraphQL query. No coding is required beyond basic configuration.
Yes. n8n has a free self-hosted option and a free trial on n8n Cloud. Cloud plans start at $20/month for higher volume. You’ll also need to factor in Shopify API usage (usually negligible for scheduled catalog pulls).
Two options: n8n Cloud (managed, easiest setup) or self-hosting on a VPS. For self-hosting, Hostinger VPS is affordable and handles n8n well. Self-hosting gives you unlimited executions but requires basic server management.
You can change what gets written to the sheet by editing the “Edit Fields (Set)” and the row-mapping logic in “Divide Results.” Common tweaks include pulling only active products, adding vendor/product type columns, saving compare-at price, or splitting variants into a separate tab. If your catalog is huge, adjust “Set Batch Limit” so each run fetches smaller chunks.
Most of the time it’s an expired access token or missing Admin API scopes on your Shopify custom app. Regenerate the token, then update the header auth in your GraphQL node in n8n. Also check that your shop domain is correct and you’re hitting the right API version. If it starts failing only on larger runs, you may be getting rate limited, so lower the batch limit or keep the built-in wait in place.
It can handle large catalogs because it paginates with cursors, so it keeps fetching until it reaches the end.
Often, yes. Zapier and Make are great for simple event-based zaps, but product catalog pulls get tricky fast because pagination, cursor state, batching, and retries matter. n8n handles branching logic cleanly, and you can self-host if you want to run a lot of scheduled syncs without watching task counts. The tradeoff is setup: you’ll spend a bit more time getting GraphQL and the sheet mapping right. If you want someone to sanity-check your setup, Talk to an automation expert.
Once your product sheet stays current on its own, planning gets a lot simpler. The workflow handles the repetitive updates, and you stop treating spreadsheets like a liability.
Need Help Setting This Up?
Our automation experts can build and customize this workflow for your specific needs. Free 15-minute consultation—no commitment required.