HomeShopify & E-commerceShopify Product Catalog Sync to Notion…

Shopify Product Catalog Sync to Notion with n8n

Shopify Product Catalog Sync to Notion with n8n








A Shopify product catalog sync to Notion keeps a Notion database mirrored to your live store, so your team plans merchandising, content, and pricing against real product data instead of a stale copy-paste. This guide builds the n8n workflow that pulls every product from Shopify on a schedule and upserts it into Notion, creating new pages and refreshing changed ones automatically. It is free to follow start to finish, and a ready-to-import template is linked below if you would rather skip the build.

Prefer to skip the setup? Grab the ready-made template and be running in under ten minutes.

What it does

This is a one-way, scheduled sync from Shopify to a Notion database. On a fixed interval, n8n asks the Shopify Admin API for your products, breaks the response into one item per product, and normalizes each one into a flat set of fields: title, SKU, price, total inventory, status, vendor, and a storefront link. For every product it then checks whether a matching page already lives in your Notion catalog, keyed on the Shopify product ID.

If a page exists, the workflow updates its price, inventory, and status. If it does not, the workflow creates a new page. The result is a Notion database that stays a faithful mirror of your catalog without anyone exporting a CSV. Notion becomes the planning surface your marketing, content, and ops people already live in, backed by live store data. This is one of the building blocks in our wider n8n Shopify automation library.

┌───────────────────────────────────────────────────────────────┐
│  SHOPIFY  ->  NOTION CATALOG SYNC                              │
│                                                               │
│  [Every 6 hours] -> [Get products] -> [Split] -> [Map fields] │
│                                                     │         │
│                                          [Find page in Notion]│
│                                                     │         │
│                                              [Page exists?]   │
│                                              /               │
│                                    [Update page]   [Create page]
└───────────────────────────────────────────────────────────────┘
  

Why it beats the default

The default way teams keep a product list in Notion is a manual export. You download a CSV from Shopify, paste it into a Notion table, and it is already out of date by the time you finish. Prices change, stock drops, a product gets archived, and the Notion copy quietly drifts from reality until nobody trusts it.

Notion has no native Shopify integration, so the usual alternative is a per-task automation platform. Those work, but they bill per operation. A catalog of a few hundred products checked several times a day burns through task quotas fast, and the cost climbs with your catalog. This n8n version runs on a flat plan or on your own server, upserts instead of blindly appending, so it never leaves duplicate rows, and it costs the same whether you sync 50 products or 5,000.

What you need

  • An n8n instance, either n8n Cloud or self-hosted. Any recent version works.
  • A Shopify store with an Admin API access token that has read_products scope. Create it through the 2026 Shopify Developer Dashboard and connect it to n8n as described in connect Shopify to n8n (2026). This workflow calls Admin API version 2026-04.
  • A Notion internal integration token, and a Notion database shared with that integration.

Your Notion database needs these properties, with these exact names and types, so the workflow can write to them:

Property Type Holds
Name Title Product title, for example Cedar Camp Mug
Shopify ID Text The Shopify product ID, the match key for upserts
Price Number First variant price, for example 24.00
Inventory Number Sum of variant inventory quantities
Status Select active, draft, or archived
SKU Text First variant SKU
Vendor Text Product vendor
Storefront URL Public product page link

Node-by-node list

  1. Every 6 hours (Schedule Trigger): fires the sync on a fixed interval.
  2. Get Shopify products (HTTP Request): GET /admin/api/2026-04/products.json?limit=250.
  3. Split into products (Split Out): turns the products array into one item per product.
  4. Map product fields (Edit Fields): normalizes each product into flat fields for Notion.
  5. Find existing page (Notion, Get Many database pages): searches Notion for a page whose Shopify ID matches.
  6. Page exists? (IF): routes on whether a matching page was found.
  7. Update Notion page (Notion, Update): refreshes price, inventory, and status on the existing page.
  8. Create Notion page (Notion, Create): adds a new catalog page for products not yet in Notion.

Step-by-step build

  1. Add a Schedule Trigger. Set it to run every 6 hours. This is the only trigger in the workflow.
  2. Add an HTTP Request node named Get Shopify products. Method GET, URL https://YOUR_STORE.myshopify.com/admin/api/2026-04/products.json?limit=250. Under Authentication choose Generic Credential Type, then Header Auth, and attach your Shopify token credential (header X-Shopify-Access-Token).
  3. Add a Split Out node named Split into products. Set Field To Split Out to products. The Shopify response is one object with a products array, so this hands the rest of the flow one item per product.
  4. Add an Edit Fields node named Map product fields. Create string and number assignments that pull from each product:
    • product_id = {{ $json.id.toString() }}
    • product_title = {{ $json.title }}
    • sku = first variant SKU
    • price = first variant price, as a number
    • inventory = sum of variant inventory quantities
    • status, vendor, and a storefront_url built from the handle
  5. Add a Notion node named Find existing page. Resource Database Page, operation Get Many. Pick your database, set Return All off with Limit 1, and add a filter: your Shopify ID property equals {{ $json.product_id }}. In the node Settings tab, turn on Always Output Data so the node still emits an item when no page is found.
  6. Add an IF node named Page exists?. Condition: {{ $json.id }} is not empty. When Notion returned a page it carries an id; when it found nothing the item is empty, so the true branch means update and the false branch means create.
  7. On the true branch, add a Notion node named Update Notion page. Operation Update, Page ID {{ $json.id }}. Map Price, Inventory, Status, SKU, and Storefront from the earlier node with {{ $('Map product fields').item.json.price }} and the like.
  8. On the false branch, add a Notion node named Create Notion page. Operation Create, pick the same database. Set the title to the product title and map Shopify ID, Price, Inventory, Status, SKU, Vendor, and Storefront from Map product fields.
  9. Wire it up: Schedule Trigger to Get Shopify products to Split into products to Map product fields to Find existing page to Page exists?, then the two branches to Update and Create.
  10. Save, run once manually, and check your Notion database. Run it a second time to confirm existing pages update rather than duplicate.
💡

Tip: Referencing $('Map product fields').item.json on both branches is what lets you drop the Notion search result and still write your product fields. There is no Merge node to configure, which keeps the two write branches clean.

Common mistakes

  • Forgetting Always Output Data on the search node. Without it, a product with no existing Notion page produces zero items, the IF never fires, and new products silently never get created. This is the single most common reason the sync appears to work but never adds anything.
  • Catalogs over 250 products. One request returns at most 250. Shopify paginates with a Link header cursor. Add a loop that follows page_info until the header is empty, or move to the GraphQL Admin API with cursor pagination.
  • Notion property name or type drift. n8n writes by property name. If Notion has Stock but the node writes Inventory, that column stays blank with no error. Keep names and types aligned with the table above.
  • Status Select options missing. If your Status property does not already contain the option being written, Notion may reject it. Pre-create active, draft, and archived, or allow n8n to add options.
  • Rate limits on large catalogs. The per-product loop calls Notion for every item. Notion allows roughly three requests per second. For big catalogs, add a small Loop Over Items batch or a short Wait so you stay under the limit.

Cost at realistic volume

All three services carry this workflow for free or close to it. The Shopify Admin API and the Notion API are both free to call at this scale. n8n Cloud counts workflow executions, not nodes or items, so a run every six hours is about 120 executions a month regardless of catalog size, which sits comfortably inside the Starter plan. Self-hosted n8n is free outright.

Component At 500 products, synced every 6 hours Cost
n8n executions ~120 per month (4 runs a day) Free tier / flat plan
Shopify Admin API ~120 product pulls per month $0
Notion API writes Up to ~60,000 upserts per month $0

Because n8n bills per execution rather than per operation, the cost does not grow with your catalog. The same run that syncs 500 products syncs 5,000 for the same execution count.

Download the ready-to-import template

The guide above is free to follow and gives you the whole workflow. If you would rather not wire eight nodes and map every Notion property by hand, the template imports the exact workflow from this post in one step. You attach your Shopify and Notion credentials, point it at your database, and the sync is live. Need it built and hosted for you instead? See our done-for-you automation service.

Download the template ($19) →

Instant download · Works on n8n Cloud and self-hosted · Matches this guide node for node

Frequently asked questions

Does this workflow create duplicate pages in Notion?

No. Before writing anything, the workflow searches your Notion database for a page whose Shopify ID matches the current product. If it finds one, it updates that page. If it does not, it creates a fresh page. That match-then-branch pattern is what makes it an upsert rather than a blind append.

How often should the catalog sync run?

Every six hours is a sensible default for a store that edits products a few times a day. If pricing or inventory changes constantly, drop it to hourly. For a small, stable catalog, once a day is plenty. You change this in the Schedule Trigger node in one click.

What if my store has more than 250 products?

The single HTTP Request returns up to 250 products. For larger catalogs, Shopify paginates with a Link header cursor. Add a loop that follows page_info until the header is empty, or switch to the GraphQL Admin API with cursor pagination. The Common mistakes section covers the fix.

Do the Notion property names have to match exactly?

Yes. n8n writes to Notion properties by name, so Price, Inventory, Status, SKU, and Storefront must exist and use the exact types the workflow expects. If you rename a property in Notion, update the matching field in the Create and Update nodes or the write silently misses that column.

Can I sync to Airtable or Google Sheets instead of Notion?

Yes. The Shopify pull and the field mapping stay identical. Swap the two Notion nodes for an Airtable upsert or a Google Sheets append-or-update on a key column. The logic is the same: match on Shopify ID, then update or create. Only the destination node changes.

Related guides

n8n
Shopify
Notion
catalog sync
automation