# Import products from Google Sheets

Imports or updates products, variants, metafields, and multi-location inventory from a Google Sheet with row-level error reporting.

Canonical URL: https://templates.jsworkflows.com/templates/import-products-from-google-sheets/

## When to use this template

This template is built for Shopify stores using the JsWorkflows app.

Use this template when you want a ready-made workflow for this use case: Imports or updates products, variants, metafields, and multi-location inventory from a Google Sheet with row-level error reporting.

It is designed for Shopify inventory and merchandising operations and gives you a production-ready starting point instead of building the automation from scratch. It can work with Google as part of the workflow.

This workflow uses the scheduled trigger model and starts from the "Daily schedule" trigger. It includes setup fields for merchant-facing values, so you can configure the workflow before installing it.

## Metadata

- Category: Inventory and merch
- Trigger: Daily schedule
- Workflow type: Scheduled
- Complexity: advanced
- Usage class: heavy-operation

## Connected services

- google

## Additional Shopify scopes

- read_products
- write_products
- read_locations
- read_inventory
- read_publications
- write_publications
- write_inventory

## Setup fields

- Spreadsheet ID (`SPREADSHEET_ID`)
  - Type: text
  - Storage: config
  - Required: yes
  - Description: The Google Sheet ID that contains the product import tab.
- Source sheet name (`SHEET_NAME`)
  - Type: text
  - Storage: config
  - Required: yes
  - Description: The tab name to read product rows from.
- Report sheet name (`REPORT_SHEET_NAME`)
  - Type: text
  - Storage: config
  - Required: no
  - Description: Optional tab used for row-level error reporting. Leave blank to disable report logging.
- Products per batch (`PRODUCTS_PER_BATCH`)
  - Type: number
  - Storage: config
  - Required: yes
  - Description: How many product jobs are grouped into each orchestration batch.
- Batch stagger seconds (`BATCH_STAGGER_SECONDS`)
  - Type: number
  - Storage: config
  - Required: yes
  - Description: Delay between orchestration batches. Increase this if you see heavy throttling.
- Product stagger seconds (`PRODUCT_STAGGER_SECONDS`)
  - Type: number
  - Storage: config
  - Required: yes
  - Description: Delay between product syncs within a batch.
- Publish to channels (`PUBLICATION_IDS`)
  - Type: shopify_publication_multiselect
  - Storage: config
  - Required: no
  - Description: Optional Shopify sales channels to publish ACTIVE products to after a successful sync.
- Google client email (`GOOGLE_CLIENT_EMAIL`)
  - Type: text
  - Storage: env
  - Required: yes
  - Description: The Google service account client email used to access Sheets.
- Google private key (`GOOGLE_PRIVATE_KEY`)
  - Type: textarea
  - Storage: env
  - Required: yes
  - Description: The full Google service account private key in PEM format, including the BEGIN/END lines. This is saved as an encrypted workflow variable after the workflow is created.

## Setup guide

## Before you start

This template reads a Google Sheet and uses Shopify `productSet` to create or update products by **Handle**.

Use this template when you want a sheet-driven product import with support for:
- full variant sync per product
- category IDs and variant-level tax/origin fields
- product and variant metafields
- product and variant images
- multi-location inventory updates
- optional auto-publishing to Shopify publications
- row-level error reporting to a report sheet

Sample file:
- [Download sample CSV](https://sample.jsworkflows.com/sample-import-products.csv)

## Sheet model

- One row = one variant
- Rows are grouped by `Handle`
- Header names matter; column order does not
- The sheet is authoritative for the variant list of each product

If a product has three desired variants, all three variants must be present in the sheet for that `Handle`.

## Required headers

- `Handle`
- `Title`
- `Variant SKU`

## Common optional headers

- `Body HTML`
- `Vendor`
- `Product Type`
- `Tags`
- `Status`
- `Gift Card`
- `Category: ID`
- `Image Src`
- `Image Alt Text`
- `Variant Price`
- `Variant Compare At Price`
- `Variant Barcode`
- `Variant Image`
- `Variant Position`
- `Variant Taxable`
- `Variant Tax Code`
- `Variant Inventory Policy`
- `Variant Cost`
- `Variant Weight`
- `Variant Weight Unit`
- `Variant Grams`
- `Variant Requires Shipping`
- `Variant Tracked`
- `Variant HS Code`
- `Variant Country of Origin`
- `Variant Province of Origin`

## Variant options

Use option columns when a product has multiple variants:
- `Option1 Name` / `Option1 Value`
- `Option2 Name` / `Option2 Value`
- `Option3 Name` / `Option3 Value`

For the same `Handle`, option names and product-level fields must stay internally consistent across all rows.

## Dynamic headers

You can add these dynamic columns:
- `Product Metafield: namespace.key|type`
- `Variant Metafield: namespace.key|type`
- `Inventory: Shopify Location Name`

Examples:
- `Product Metafield: custom.material|single_line_text_field`
- `Variant Metafield: specs.origin_country|single_line_text_field`
- `Inventory: Sydney Warehouse`

## Additional supported fields

- `Category: ID` must be a valid Shopify taxonomy category ID
- `Image Alt Text` is applied to each image URL listed on that row
- `Variant Image` attaches an image URL to a specific variant and also includes it in the product file list
- `Variant Weight` should be paired with `Variant Weight Unit` (`g`, `kg`, `oz`, or `lb`)
- `Variant Grams` still works and is used as a fallback when `Variant Weight` is not provided

## Publishing behavior

If you select one or more Shopify sales channels during setup, ACTIVE products are published to those destinations after a successful sync.

The setup UI loads the shop's live publications and stores their publication IDs, so the workflow publishes by Shopify publication ID instead of typed names.

## Error reporting

If `Report sheet name` is set, the template appends row-level failures to that tab.

Create the report tab before running the template. Leave the field blank to disable report logging.

## Google credentials

The template setup form saves these as workflow secrets:
- `GOOGLE_CLIENT_EMAIL`
- `GOOGLE_PRIVATE_KEY`

Paste the full PEM private key including the `BEGIN` and `END` lines.

## Operational notes

- `productSet` replaces the variant list for each Handle
- Inventory columns must match Shopify location names exactly, or be a unique case-insensitive match
- This template updates only fields represented in the sheet; it does not clear unrelated scalar product fields
- Increase pacing delays if you see throttling on large catalogs

