Sanity Connect for Shopify - Reference
Reference documentation and code examples to set up and configure Sanity Connect for Shopify
You will find all data synced from Shopify under the store
property of each document. Typically, you want to set these fields as readOnly
or hidden
in your Sanity Studio schemas.
All products sync from Shopify into Sanity, and we attempt to keep the Status
in Shopify linked to the publishing state in Sanity.
- If a product is 'Draft' in Shopify
- The document is created as unpublished in Sanity.
- Any changes to the product cascade to the unpublished draft in Sanity.
- If a product is 'Active' in Shopify
- The document is created as published in Sanity.
- Any changes to the product cascade to the published document as well as any unpublished draft.
If a product is Archived or switched to the 'Draft' status, then we attempt to unpublish the matched document in Sanity. This operation will fail if the published Sanity document is referenced by another document in your dataset. We allow the operation to fail, and we will attempt to unpublish the document again on the next sync.
Because 'Draft' products are not published, we do not support syncing custom fields as Shopify metafields on draft products. These custom fields will sync once the product is switched to 'Active'.
This is an example of a product document. Note the array of references to variant documents.
{
"_createdAt": "2022-05-18T07:45:26Z",
"_id": "shopifyProduct-7696133062907",
"_rev": "sERZ3ZJ9MtNiP4BmT5zftt",
"_type": "product",
"_updatedAt": "2022-08-31T21:41:10Z",
"body": [],
"store": {
"createdAt": "2022-05-12T17:39:51+01:00",
"descriptionHtml": "",
"gid": "gid://shopify/Product/7696133062907",
"id": 7696133062907,
"isDeleted": false,
"options": [
{
"_key": "Color",
"_type": "option",
"name": "Color",
"values": [
"Blue",
"Ecru",
"Pink"
]
}
],
"previewImageUrl": "https://cdn.shopify.com/s/files/1/0639/3285/8619/products/Green_1.jpg?v=1655598944",
"priceRange": {
"maxVariantPrice": 25.5,
"minVariantPrice": 25
},
"productType": "",
"slug": {
"_type": "slug",
"current": "soap-dish"
},
"status": "active",
"tags": "",
"title": "AUTOGRAF Soap Dish",
"variants": [
{
"_key": "c8b492e1-3c24-527d-bffd-accc634177c7",
"_ref": "shopifyProductVariant-43068621422843",
"_type": "reference",
"_weak": true
},
{
"_key": "9128c62c-f887-594c-b9b8-ddaaf850ce84",
"_ref": "shopifyProductVariant-43068621455611",
"_type": "reference",
"_weak": true
},
{
"_key": "5d861cdf-bcfe-5781-81dd-d62db159442b",
"_ref": "shopifyProductVariant-43068621488379",
"_type": "reference",
"_weak": true
}
],
"vendor": "Lucy Holdberg"
}
}
This is an example of a variant document.
{
"_createdAt": "2022-05-27T08:49:54Z",
"_id": "shopifyProductVariant-43068621422843",
"_rev": "sERZ3ZJ9MtNiP4BmT5zftt",
"_type": "productVariant",
"_updatedAt": "2022-08-31T21:32:01Z",
"store": {
"compareAtPrice": 35,
"createdAt": "2022-05-27T09:49:52+01:00",
"gid": "gid://shopify/ProductVariant/43068621422843",
"id": 43068621422843,
"inventory": {
"isAvailable": true,
"management": "SHOPIFY",
"policy": "CONTINUE"
},
"isDeleted": false,
"option1": "Blue",
"option2": "",
"option3": "",
"previewImageUrl": "https://cdn.shopify.com/s/files/1/0639/3285/8619/products/Blue_1.jpg?v=1655598950",
"price": 25.5,
"productGid": "gid://shopify/Product/7696133062907",
"productId": 7696133062907,
"sku": "AGSD_BLUE",
"status": "active",
"title": "Blue"
}
}
This is an example of a collection document:
{
"_createdAt": "2022-06-07T10:00:11Z",
"_id": "shopifyCollection-396461834491",
"_rev": "0penztPZlC32Cv2tesREk7",
"_type": "collection",
"_updatedAt": "2022-08-26T15:07:57Z",
"store": {
"createdAt": "2022-08-26T15:07:56.895Z",
"descriptionHtml": "",
"disjunctive": false,
"gid": "gid://shopify/Collection/396461834491",
"id": 396461834491,
"imageUrl": "https://cdn.shopify.com/s/files/1/0639/3285/8619/collections/BLOMST_print.jpg?v=1655599663",
"isDeleted": false,
"rules": [
{
"_key": "7803ad21-682e-56b6-ae2a-4d380d0d120c",
"_type": "object",
"column": "TYPE",
"condition": "Poster",
"relation": "CONTAINS"
}
],
"slug": {
"_type": "slug",
"current": "prints"
},
"sortOrder": "BEST_SELLING",
"title": "Prints"
}
}
Below are the data types for the properties of a collection document:
export type ShopifyDocumentCollection = {
_id: `shopifyCollection-${string}` // Shopify product ID
_type: 'collection'
store: {
id: number
gid: `gid://shopify/Collection/${string}`
createdAt: string
isDeleted: boolean
descriptionHtml: string
imageUrl?: string
rules?: {
_key: string
_type: 'object'
column: Uppercase<string>
condition: string
relation: Uppercase<string>
}[]
disjunctive?: boolean
slug: {
_type: 'slug'
current: string
}
sortOrder: string
title: string
updatedAt: string
}
}
If you use the custom webhook sync, your handler will receive the shape described Product
(and Collection
if enabled) below. You can still use JavaScript or any other programming language in your custom handler even though we describe the payload using TypeScript syntax.
export type Product = {
id: `gid://shopify/ProductVariant/${string}`
title: string
description: string
descriptionHtml: string
featuredImage?: ProductImage
handle: string
images: ProductImage[]
options: ProductOption[]
priceRange: ProductPriceRange
productType: string
tags: string[]
variants: ProductVariant[]
vendor: string
status: 'active' | 'archived' | 'draft' | 'unknown'
publishedAt: string
createdAt: string
updatedAt: string
}
export type ProductImage = {
id: `gid://shopify/ProductImage/${string}`
altText?: string
height?: number
width?: number
src: string
}
export type ProductOption = {
id: `gid://shopify/ProductOption/${string}`
name: string
position: number
values: string[]
}
export type ProductPriceRange = {
minVariantPrice?: number
maxVariantPrice?: number
}
export type ProductVariant = {
id: `gid://shopify/ProductVariant/${string}`
title: string
compareAtPrice?: number
barcode?: string
inventoryPolicy: string
inventoryQuantity: number
inventoryManagement: string
position: number
requiresShipping: boolean
sku: string
taxable: boolean
weight: number
weightUnit: string
price: string
createdAt: string
updatedAt: string
image?: ProductImage
product: {
id: `gid://shopify/Product/${string}`
status: 'active' | 'archived' | 'draft' | 'unknown'
}
selectedOptions: {
name: string
values: string[]
}[]
}
export type Collection = {
id: `gid://shopify/Collection/${string}`
createdAt: string
handle: string
descriptionHtml: string
image?: CollectionImage
rules?: {
column: string
condition: string
relation: string
}[]
disjunctive?: boolean
sortOrder: string
title: string
updatedAt: string
}
export type CollectionImage = {
altText: string
height?: number
width?: number
src: string
}
// When products are created, updated or manually synced
export type payloadProductsSync = {
action: 'create' | 'update' | 'sync'
products: Product[]
}
// When products are deleted
export type payloadProductsDelete = {
action: 'delete'
productIds: number[]
}
// When collections are created, updated or manually synced
export type payloadCollectionsSync = {
action: 'create' | 'update' | 'sync'
collections: Collection[]
}
// When collections are deleted
export type payloadCollectionsDelete = {
action: 'delete'
collectionIds: number[]
}
export type requestPayload = payloadProductsDelete | payloadProductsSync | payloadCollectionsDelete | payloadCollectionsSync