This workflow corresponds to n8n.io template #9833 — we link there as the canonical source.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"meta": {
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "ba37e8c9-0372-443a-92cc-55d7893547cc",
"name": "When clicking \u2018Execute workflow\u2019",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-720,
320
],
"parameters": {},
"typeVersion": 1
},
{
"id": "454305c0-5593-4340-9224-dee5c937acdb",
"name": "Get row(s) in sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
0,
320
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": 2048403983,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1y7HlsC35Rn_fRtJ7GvJ38F0Aw9sycJ4New80lTOR0hc/edit#gid=2048403983",
"cachedResultName": "Products"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1y7HlsC35Rn_fRtJ7GvJ38F0Aw9sycJ4New80lTOR0hc",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1y7HlsC35Rn_fRtJ7GvJ38F0Aw9sycJ4New80lTOR0hc/edit?usp=drivesdk",
"cachedResultName": "Shopify Store Details"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "b6b0846a-1b94-438b-b518-7ed51b3bdc6a",
"name": "Shopify, GetLocations",
"type": "n8n-nodes-base.graphql",
"position": [
-240,
320
],
"parameters": {
"query": "query {\n locations(first:1, reverse:true) {\n edges {\n node {\n id\n name\n address {\n address1\n address2\n city\n country\n zip\n province\n }\n }\n }\n }\n}",
"endpoint": "={{ $('set shop url').item.json.myshop }}",
"authentication": "headerAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"executeOnce": true,
"typeVersion": 1.1
},
{
"id": "b7a3b2c1-0f79-4233-8731-1d5631dccd93",
"name": "Shopify, CreateProduct",
"type": "n8n-nodes-base.graphql",
"position": [
784,
64
],
"parameters": {
"query": "=mutation productCreate($product: ProductCreateInput!, $media: [CreateMediaInput!]) {\n productCreate(product: $product, media: $media) {\n product {\n id\n title\n handle\n options {\n id\n name\n position\n optionValues {\n id\n name\n }\n }\n variants(first:10) {\n edges {\n node {\n id\n sku\n displayName\n inventoryItem {\n id\n sku\n tracked\n requiresShipping\n }\n }\n }\n }\nmedia(first: 10) {\n edges {\n node {\n alt\n mediaContentType\n status\n id\n preview {\n image {\n url\n }\n status\n }\n }\n }\n }\n }\n userErrors {\n field\n message\n }\n }\n}",
"endpoint": "={{ $('set shop url').first().json.myshop }}",
"variables": "={\n \"product\": {\n \"title\": \"{{ $json.productName }}\",\n \"vendor\": \"vendor.\",\n \"productType\": \"type\",\n \"status\": \"ACTIVE\",\n \"handle\": \"{{ $json.productName.toLowerCase().replaceAll(' ', '-') }}\",\n \"productOptions\": \n{{JSON.stringify($json.optionsGraph) }}\n },\n \"media\": [\n {\n \"alt\": \"{{ $json.productName }}\",\n \"mediaContentType\": \"IMAGE\",\n \"originalSource\": \"{{ $json.productImage }}\"\n }\n ]\n}",
"authentication": "headerAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "a1171896-5b8f-4bb8-8d8f-bfc208d86f0b",
"name": "Split Out1",
"type": "n8n-nodes-base.splitOut",
"position": [
1280,
64
],
"parameters": {
"include": "selectedOtherFields",
"options": {},
"fieldToSplitOut": "variants",
"fieldsToInclude": "productId, productTitle, mainfirstVariant, mediaID"
},
"typeVersion": 1
},
{
"id": "4a93dc5f-19a4-4c14-b48f-0de54e24f226",
"name": "SetVariant",
"type": "n8n-nodes-base.graphql",
"position": [
1504,
64
],
"parameters": {
"query": "mutation ProductVariantsCreate($productId: ID!, $variants: [ProductVariantsBulkInput!]!) {\n productVariantsBulkCreate(productId: $productId, variants: $variants) {\n productVariants {\n id\n sku\n title\n price\n compareAtPrice\ninventoryItem {\n id\n sku\n tracked\n requiresShipping\n }\n \n selectedOptions {\n name\n value\n }\n }\n userErrors { \n\n field\n message\n }\n }\n }",
"endpoint": "={{ $('set shop url').first().json.myshop }}",
"variables": "={\n \"productId\": \"{{ $json.productId }}\",\n \"variants\": [\n {\n \"price\": {{ $json.variants.price }},\n \"optionValues\": [\n {\n \"name\": \"{{ $json.variants.inventoryItem.size }}\",\n \n \"optionId\": \"{{ $json.variants.optionValues[0].optionId }}\"\n }\n ]\n }\n ]\n}",
"authentication": "headerAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "364a6a32-401c-4cc5-9f7c-7d985097d522",
"name": "Update Variants",
"type": "n8n-nodes-base.graphql",
"position": [
1936,
64
],
"parameters": {
"query": "mutation productVariantsBulkUpdate($productId: ID!, $variants: [ProductVariantsBulkInput!]!) {\n productVariantsBulkUpdate(productId: $productId, variants: $variants) {\n product {\n id\n handle\n }\n productVariants {\n id\n sku\n title\n price\n compareAtPrice\ninventoryItem {\n id\n sku\n tracked\n requiresShipping\n }\n }\n userErrors {\n field\n message\n }\n }\n}",
"endpoint": "={{ $('set shop url').first().json.myshop }}",
"variables": "={\n \"productId\": \"{{ $json.productId }}\",\n \"variants\": {\n \"id\" : \"{{ $json.data.productVariantsBulkCreate.productVariants[0].id }}\",\n \"price\" : \"{{ $('is variant?').item.json.basePrice }}\",\n \"inventoryItem\": {\n \"sku\": \"{{ $json.variants.inventoryItem.sku }}\",\n \"tracked\": true\n }\n }\n}",
"authentication": "headerAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "22739e81-498d-4608-b59a-bec8b39935cf",
"name": "SetInventory",
"type": "n8n-nodes-base.graphql",
"position": [
2160,
64
],
"parameters": {
"query": "mutation inventorySetOnHandQuantities($input: InventorySetOnHandQuantitiesInput!) {\n inventorySetOnHandQuantities(input: $input) {\n userErrors {\n field\n message\n }\n }\n}",
"endpoint": "={{ $('set shop url').first().json.myshop }}",
"variables": "={\n \"input\" : {\n \"reason\": \"correction\",\n \"setQuantities\" :[{\n \"inventoryItemId\":\"{{ $json.data.productVariantsBulkUpdate.productVariants[0].inventoryItem.id }}\",\n \"locationId\": \"{{ $('Shopify, GetLocations').first().json.data.locations.edges[0].node.id }}\",\n \"quantity\" : {{ $('set variants data').item.json.variants.inventoryItem.inventory }}\n }]\n }\n}",
"authentication": "headerAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "397d171a-5cb1-45b8-8f47-cced0dc1e90a",
"name": "SetVariant1",
"type": "n8n-nodes-base.graphql",
"position": [
1040,
512
],
"parameters": {
"query": "mutation productVariantsBulkUpdate($productId: ID!, $variants: [ProductVariantsBulkInput!]!) {\n productVariantsBulkUpdate(productId: $productId, variants: $variants) {\n product {\n id\n handle\n }\n productVariants {\n id\n sku\n title\n price\n compareAtPrice\n }\n userErrors {\n field\n message\n }\n }\n}",
"endpoint": "={{ $('set shop url').first().json.myshop }}",
"variables": "={\n \"productId\": \"{{ $json.data.productCreate.product.id }}\",\n \"variants\": {\n \"id\" : \"{{ $json.data.productCreate.product.variants.edges[0].node.id }}\",\n \"price\" : \"{{ $('is variant?').item.json.price }}\",\n \"inventoryItem\": {\n \"sku\": \"{{ $('is variant?').item.json.fullSKU }}\",\n \"tracked\": true\n }\n }\n}",
"authentication": "headerAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "2a69bd47-ca48-4699-b5eb-f1ec16753fca",
"name": "CreateProduct2",
"type": "n8n-nodes-base.graphql",
"position": [
784,
512
],
"parameters": {
"query": "mutation productCreate($product: ProductCreateInput!, $media: [CreateMediaInput!]) {\n productCreate(product: $product, media: $media) {\n product {\n id\n title\n descriptionHtml\n vendor\n productType\n status\n handle\n variants(first:10) {\n edges {\n node {\n id\n sku\n displayName\n inventoryItem {\n id\n sku\n tracked\n requiresShipping\n }\n }\n }\n }\n media(first: 10) {\n edges {\n node {\n alt\n mediaContentType\n status\n id\n preview {\n image {\n url\n }\n status\n }\n }\n }\n }\n options {\n id\n name\n position\n optionValues {\n id\n name\n hasVariants\n }\n }\n }\n userErrors {\n field\n message\n }\n }\n}",
"endpoint": "={{ $('set shop url').first().json.myshop }}",
"variables": "={\n \"product\": {\n \"title\": \" {{ $json.productName }} \",\n \"vendor\" : \"vendor.\",\n \"productType\": \"type\",\n \"status\": \"ACTIVE\",\n \"handle\": \"{{ $json.productName.replaceAll(\" \", \"-\") }}\"\n },\n \"media\" : [{\n \"alt\" : \"{{ $json.productName }}\",\n \"mediaContentType\" : \"IMAGE\",\n \"originalSource\" : \"{{ $json.productImage }}\"\n }]\n}",
"authentication": "headerAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "61e04df6-43f7-4a40-988f-860bd334b16c",
"name": "Create SetInventory",
"type": "n8n-nodes-base.graphql",
"position": [
1280,
512
],
"parameters": {
"query": "mutation inventorySetOnHandQuantities($input: InventorySetOnHandQuantitiesInput!) {\n inventorySetOnHandQuantities(input: $input) {\n userErrors {\n field\n message\n }\n }\n}",
"endpoint": "={{ $('set shop url').first().json.myshop }}",
"variables": "={\n \"input\" : {\n \"reason\": \"correction\",\n \"setQuantities\" :[{\n \"inventoryItemId\":\"{{ $('CreateProduct2').item.json.data.productCreate.product.variants.edges[0].node.inventoryItem.id }}\",\n \"locationId\": \"{{ $('Shopify, GetLocations').first().json.data.locations.edges[0].node.id }}\",\n \"quantity\" : {{ $('is variant?').item.json.inventory }}\n }]\n }\n}",
"authentication": "headerAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "ef9bb27c-ee31-4a4a-8574-ba03ce6cb368",
"name": "single and multivariant products",
"type": "n8n-nodes-base.code",
"position": [
240,
320
],
"parameters": {
"jsCode": "// n8n Code Node - Product Variant Processor\n// This processes products and groups them by variants\nconst items = $input.all();\n\n// Helper function to extract base SKU and variant suffix\nfunction parseVariantSKU(sku) {\n const skuStr = String(sku);\n const parts = skuStr.split('-');\n \n if (parts.length > 1) {\n const baseSKU = parts[0];\n const variantSuffix = parts.slice(1).join('-');\n return { baseSKU, variantSuffix, isVariant: true };\n }\n \n return { baseSKU: skuStr, variantSuffix: '', isVariant: false };\n}\n\n// Group products by Product Name\nconst productGroups = {};\n\nitems.forEach(item => {\n const data = item.json;\n const productName = data['Product Name'];\n \n if (!productGroups[productName]) {\n productGroups[productName] = [];\n }\n \n productGroups[productName].push(data);\n});\n\n// Build output array\nconst output = [];\n\nObject.keys(productGroups).forEach(productName => {\n const variants = productGroups[productName];\n const hasVariants = variants.length > 1 || (variants.length === 1 && variants[0].Size !== '');\n \n if (hasVariants) {\n // Product with variants - prepare all variant data\n const totalInventory = variants.reduce((sum, v) => sum + v['On hand Inventory'], 0);\n const basePrice = variants[0].Price;\n const baseSKU = parseVariantSKU(variants[0].SKU).baseSKU;\n \n // Build optionsGraph dynamically based on variant count\n const optionsGraph = [\n {\n name: \"Size\",\n values: variants.map(v => {\n const parsed = parseVariantSKU(v.SKU);\n return { name: v.Size || parsed.variantSuffix };\n })\n }\n ];\n \n output.push({\n json: {\n type: 'variant',\n productName: productName,\n baseSKU: baseSKU,\n basePrice: basePrice,\n totalInventory: totalInventory,\n variantCount: variants.length,\n productImage: variants[0]['Product Image'],\n // GraphQL options format\n optionsGraph: optionsGraph,\n // Format variants for Shopify productCreate mutation\n variantsForCreate: variants.map(v => {\n const parsed = parseVariantSKU(v.SKU);\n return {\n optionValues: [{ optionName: \"Size\", name: v.Size || parsed.variantSuffix }],\n price: String(v.Price),\n inventoryItem: {\n sku: String(v.SKU),\n tracked: true\n },\n inventoryQuantities: {\n availableQuantity: v['On hand Inventory'],\n locationId: \"LOCATION_ID_PLACEHOLDER\" // Will be replaced\n }\n };\n }),\n // Keep individual variant data for inventory updates\n variants: variants.map(v => {\n const parsed = parseVariantSKU(v.SKU);\n return {\n productName: productName,\n fullSKU: String(v.SKU),\n variantTitle: v.Size || parsed.variantSuffix,\n size: v.Size,\n inventory: v['On hand Inventory'],\n image: variants[0]['Product Image'],\n price: v.Price\n };\n })\n }\n });\n } else {\n // Single product (no variants)\n const product = variants[0];\n const parsed = parseVariantSKU(product.SKU);\n \n output.push({\n json: {\n type: 'single',\n productName: productName,\n baseSKU: parsed.baseSKU,\n fullSKU: String(product.SKU),\n price: product.Price,\n inventory: product['On hand Inventory'],\n productImage: product['Product Image']\n }\n });\n }\n});\n\nreturn output;"
},
"typeVersion": 2
},
{
"id": "6f41fc6d-f06e-4ab3-a2af-cf0983690edb",
"name": "is variant?",
"type": "n8n-nodes-base.switch",
"position": [
416,
320
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "Variant",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "843be2ff-a953-4ecc-a547-261adfcf3678",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.type }}",
"rightValue": "variant"
}
]
},
"renameOutput": true
},
{
"outputKey": "Single",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "7e1926e9-bc68-4cee-a697-5fad1564f903",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.type }}",
"rightValue": "single"
}
]
},
"renameOutput": true
}
]
},
"options": {}
},
"typeVersion": 3.3
},
{
"id": "6b4b776c-08f3-4442-af5a-393b575ae14f",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1728,
-592
],
"parameters": {
"color": 3,
"width": 960,
"height": 1280,
"content": "\n\n# Shopify Product Importer with Variants Support\n\n## Setup Guidelines\n\n\ud83d\udd27 Setup Instructions\n### Step 1: Configure Shopify Credentials\n\nIn n8n, create a new Header Auth credential\nSet these values:\n\nName: X-Shopify-Access-Token\nValue: Your Shopify Admin API Access Token\n\n\n\n### Step 2: Update Workflow Nodes\n\nShopify, GetLocations node:\n\nUpdate the endpoint with your store URL\nSelect your Shopify credentials\n\n\nGet row(s) in sheet node:\n\nConnect your Google Sheets account\nSelect your spreadsheet\nChoose the sheet with product data\n\n\nUpdate all other Shopify nodes with:\n\nYour store URL (replace myshop.myshopify.com)\nYour Shopify credentials\n\n\n\n### Step 3: Customize Product Details (Optional)\nIn the workflow, you can customize these defaults:\n\nFor variant products (in Shopify, CreateProduct node):\n\njavascript\"vendor\": \"vendor\", // Change to your vendor name\n\"productType\": \"type\", // Change to your product type\n\nFor single products (in CreateProduct2 node):\n\njavascript\"vendor\": \"vendor\", // Change to your vendor name\n\"productType\": \"type\", // Change to your product type"
},
"typeVersion": 1
},
{
"id": "4d167268-e51e-4451-8850-73258c233d25",
"name": "set shop url",
"type": "n8n-nodes-base.set",
"position": [
-480,
320
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "3b280df6-01c4-4db0-a53c-4e6579f3ba36",
"name": "myshop",
"type": "string",
"value": "https://[yourshop].myshopify.com/admin/api/2025-04/graphql.json"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "43c3ad5c-2a17-4d87-8d08-d8e4412429d4",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-544,
176
],
"parameters": {
"width": 256,
"height": 336,
"content": "## Add your store subdomain \n**https://[yourshop].myshopify.com/**"
},
"typeVersion": 1
},
{
"id": "6d1fe3be-cec8-4517-9759-6aa774c1d3fb",
"name": "set variants data",
"type": "n8n-nodes-base.set",
"position": [
1712,
64
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "cf7e0057-939e-4b3c-9654-ef05c2ece564",
"name": "variants.optionValues[0].optionId",
"type": "string",
"value": "={{ $('Split Out1').item.json.variants.optionValues[0].optionId }}"
},
{
"id": "75d5c47f-2614-416a-91fe-540ef44b5ea2",
"name": "variants.price",
"type": "string",
"value": "={{ $('Split Out1').item.json.variants.price }}"
},
{
"id": "0215f465-592a-4724-9412-8147abce1f83",
"name": "variants.inventoryItem.sku",
"type": "string",
"value": "={{ $('Split Out1').item.json.variants.inventoryItem.sku }}"
},
{
"id": "25e5b917-267b-4073-a1e1-5b3bf7bdc34d",
"name": "variants.inventoryItem.inventory",
"type": "number",
"value": "={{ $('Split Out1').item.json.variants.inventoryItem.inventory }}"
},
{
"id": "55109d6c-1599-4414-95ec-47d2aa631284",
"name": "variants.inventoryItem.size",
"type": "string",
"value": "={{ $('Split Out1').item.json.variants.inventoryItem.size }}"
},
{
"id": "53a71947-ca2c-4c19-9dfc-f16c9284f703",
"name": "variants.inventoryItem.image",
"type": "string",
"value": "={{ $('Split Out1').item.json.variants.inventoryItem.image }}"
},
{
"id": "f6a87447-64f2-4a46-a901-da105b8d679a",
"name": "data.productVariantsBulkCreate.productVariants[0].id",
"type": "string",
"value": "={{ $json.data.productVariantsBulkCreate.productVariants[0]?.id ? $json.data.productVariantsBulkCreate.productVariants[0].id : $('Split Out1').item.json.mainfirstVariant }}"
},
{
"id": "22d4abec-4a92-45a9-9473-bc6a1fa7324a",
"name": "productId",
"type": "string",
"value": "={{ $('Split Out1').item.json.productId }}"
},
{
"id": "3cb2cda3-613b-483c-89a1-f316ca0e1050",
"name": "productTitle",
"type": "string",
"value": "={{ $('Split Out1').item.json.productTitle }}"
},
{
"id": "0566352e-70b1-4c20-ad74-560400066cde",
"name": "mediaID",
"type": "string",
"value": "={{ $('Split Out1').item.json.mediaID }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "e4b35802-52dc-472e-82a4-b1669270636c",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
704,
-80
],
"parameters": {
"color": 4,
"width": 256,
"height": 784,
"content": "### Use fixed 'type' and 'vendor' or update the json variables to pass these variables."
},
"typeVersion": 1
},
{
"id": "3645bfc0-26b1-405d-8c15-acc984db508a",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1200,
-80
],
"parameters": {
"color": 4,
"width": 256,
"height": 336,
"content": "### this split node will split variants into individual items to be created and updated in next steps"
},
"typeVersion": 1
},
{
"id": "58961d0d-74e5-4bfb-882d-e34ac397aea4",
"name": "adjust variants",
"type": "n8n-nodes-base.code",
"position": [
1024,
64
],
"parameters": {
"jsCode": "// Get ALL items from the previous step (all created products)\nconst items = $input.all();\n\n// Get the original variants data from Switch node (all variant products)\nconst switchItems = $('is variant?').all();\n// Process each product\nconst output = items.map((item, index) => {\n // Get the created product data\n const productData = item.json.data.productCreate.product;\n const productId = productData.id;\n const mainVariant = item.json.data.productCreate.product.variants.edges[0].node.id\n const mediaId = item.json.data.productCreate.product.media.edges[0].node.id\n\n // Get the Size option - it should exist now\n const sizeOption = productData.options.find(opt => opt.name === \"Size\");\n\n if (!sizeOption) {\n throw new Error(`Size option not found in created product: ${productData.title}`);\n }\n\n // Get the corresponding original variant data for this product\n const variantsData = switchItems[index].json.variants;\n\n // Build variants array for productVariantsBulkCreate\n // Match each variant with its corresponding optionValue ID\n const variantsForCreate = variantsData.map(variant => {\n // Find the matching option value ID for this size\n const optionValue = sizeOption.optionValues.find(ov => ov.name === variant.size);\n \n if (!optionValue) {\n throw new Error(`Option value not found for size: ${variant.size}`);\n }\n \n return {\n optionValues: [\n {\n optionId: sizeOption.id,\n id: optionValue.id\n }\n ],\n price: String(variant.price),\n inventoryItem: {\n sku: variant.fullSKU,\n inventory: variant.inventory,\n size: variant.size,\n image: variant.image,\n tracked: true\n }\n };\n });\n\n return {\n json: {\n productId: productId,\n productTitle: productData.title,\n mainfirstVariant: mainVariant,\n mediaID: mediaId,\n \n variants: variantsForCreate,\n originalVariantsData: variantsData\n }\n };\n});\n\nreturn output;"
},
"typeVersion": 2
},
{
"id": "144915d0-e6d6-4861-b454-a3eb19d9a137",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-96,
176
],
"parameters": {
"width": 256,
"height": 336,
"content": "## Connect your table ( source of products)\n** table with title, SKU, picture url, price, inventory and/or vendor, type **"
},
"typeVersion": 1
}
],
"connections": {
"SetVariant": {
"main": [
[
{
"node": "set variants data",
"type": "main",
"index": 0
}
]
]
},
"Split Out1": {
"main": [
[
{
"node": "SetVariant",
"type": "main",
"index": 0
}
]
]
},
"SetVariant1": {
"main": [
[
{
"node": "Create SetInventory",
"type": "main",
"index": 0
}
]
]
},
"is variant?": {
"main": [
[
{
"node": "Shopify, CreateProduct",
"type": "main",
"index": 0
}
],
[
{
"node": "CreateProduct2",
"type": "main",
"index": 0
}
]
]
},
"SetInventory": {
"main": [
[]
]
},
"set shop url": {
"main": [
[
{
"node": "Shopify, GetLocations",
"type": "main",
"index": 0
}
]
]
},
"CreateProduct2": {
"main": [
[
{
"node": "SetVariant1",
"type": "main",
"index": 0
}
]
]
},
"Update Variants": {
"main": [
[
{
"node": "SetInventory",
"type": "main",
"index": 0
}
]
]
},
"adjust variants": {
"main": [
[
{
"node": "Split Out1",
"type": "main",
"index": 0
}
]
]
},
"set variants data": {
"main": [
[
{
"node": "Update Variants",
"type": "main",
"index": 0
}
]
]
},
"Get row(s) in sheet": {
"main": [
[
{
"node": "single and multivariant products",
"type": "main",
"index": 0
}
]
]
},
"Shopify, GetLocations": {
"main": [
[
{
"node": "Get row(s) in sheet",
"type": "main",
"index": 0
}
]
]
},
"Shopify, CreateProduct": {
"main": [
[
{
"node": "adjust variants",
"type": "main",
"index": 0
}
]
]
},
"single and multivariant products": {
"main": [
[
{
"node": "is variant?",
"type": "main",
"index": 0
}
]
]
},
"When clicking \u2018Execute workflow\u2019": {
"main": [
[
{
"node": "set shop url",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
googleSheetsOAuth2ApihttpHeaderAuth
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Import products from Google Sheets to Shopify with automatic handling of single products and multi-variant products (sizes, colors, etc.). Includes SKU management, inventory tracking, and image uploads via GraphQL API. E-commerce Productivity Data Import/Export
Source: https://n8n.io/workflows/9833/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow creates products in your Shopify store from a google sheet. It also enables inventory tracking and sets the quantity of an inventory item at your store's default location.
Read a list of customers from a GoogleSheet and create them in Shopify using Shopify's Admin API (GraphQL). Generate test users for development stores. Migrate customers from other platforms. Easy int
This template is ideal for solo store owners, eCommerce marketers, automation beginners, or anyone using Shopify and Gmail who wants to recover lost revenue without coding.
PCN. Uses googleSheets, httpRequest, @n-octo-n/n8n-nodes-json-database, itemLists. Event-driven trigger; 60 nodes.
The workflow automates the process of gathering extensive keyword data for a "Main Keyword." It starts by reading initial parameters from a Google Sheets template, creates a new dedicated Google Sheet