diff --git a/docs/.vitepress/theme/components/ScopeTable.vue b/docs/.vitepress/theme/components/ScopeTable.vue new file mode 100644 index 0000000..93d3344 --- /dev/null +++ b/docs/.vitepress/theme/components/ScopeTable.vue @@ -0,0 +1,237 @@ + + + + + diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts index 25c06a7..984c8c9 100644 --- a/docs/.vitepress/theme/index.ts +++ b/docs/.vitepress/theme/index.ts @@ -7,6 +7,7 @@ import FeatureGrid from './components/FeatureGrid.vue' import FeatureCard from './components/FeatureCard.vue' import VideoEmbed from './components/VideoEmbed.vue' import GoogleTranslate from './components/GoogleTranslate.vue' +import ScopeTable from './components/ScopeTable.vue' import './custom.css' export default { @@ -19,6 +20,7 @@ export default { app.component('FeatureCard', FeatureCard) app.component('VideoEmbed', VideoEmbed) app.component('GoogleTranslate', GoogleTranslate) + app.component('ScopeTable', ScopeTable) app.directive('click-outside', { mounted(el, binding) { diff --git a/docs/shopify/attribute-mapping.md b/docs/shopify/attribute-mapping.md index 3dbf2e6..5dfced2 100644 --- a/docs/shopify/attribute-mapping.md +++ b/docs/shopify/attribute-mapping.md @@ -16,48 +16,57 @@ On this screen, the left side lists all available Shopify product fields. For ea ## Available Field Mappings -Here's a breakdown of every Shopify field you can map, what it does, and when you'd use it: - -| Shopify Field | Field Code | What it does | -|---|---|---| -| **Name** | `title` | The product title shown on your Shopify storefront | -| **Description** | `descriptionHtml` | Full product description — supports HTML formatting | -| **Price** | `price` | The selling price of the product | -| **Weight** | `weight` | Product weight used for shipping calculations | -| **Quantity** | `inventoryQuantity` | How many units are available in stock | -| **Inventory Tracked** | `inventoryTracked` | Turns on inventory tracking for the product | -| **Allow Purchase Out of Stock** | `inventoryPolicy` | Allows customers to still buy the product when stock hits zero | -| **Vendor** | `vendor` | The brand or supplier name | -| **Product Type** | `productType` | The category or type the product belongs to | -| **Tags** | `tags` | Keywords used for search and filtering in Shopify | -| **Barcode** | `barcode` | Product barcode or unique identifier for inventory scanning | -| **Compare Price** | `compareAtPrice` | The original price — shown as a strikethrough to highlight a discount | -| **SEO Title** | `metafields_global_title_tag` | Custom page title used by search engines | -| **SEO Description** | `metafields_global_description_tag` | Meta description shown in search engine results | -| **Handle** | `handle` | The URL-friendly slug for the product page (e.g. `blue-running-shoes`) | -| **Taxable** | `taxable` | Marks whether tax should be applied to this product | -| **Cost per Item** | `cost` | Cost of goods sold (COGS) — used for profit reporting | +Here's a breakdown of every Shopify field you can map, what it does, and which UnoPim attribute types it accepts: + +| Shopify Field | Field Code | What it does | Supported attribute types | +|---|---|---|---| +| **Name** | `title` | The product title shown on your Shopify storefront. This field is required. | text | +| **Description** | `descriptionHtml` | Full product description — supports HTML formatting | text, textarea | +| **Price** | `price` | The selling price of the product | price | +| **Weight** | `weight` | Product weight used for shipping calculations | number, metric | +| **Inventory Tracked** | `inventoryTracked` | Turns on inventory tracking for the product | boolean | +| **Allow Purchase Out of Stock** | `inventoryPolicy` | Allows customers to still buy the product when stock hits zero | yes/no | +| **Vendor** | `vendor` | The brand or supplier name | text, simple select | +| **Product Type** | `productType` | The category or type the product belongs to | text, simple select | +| **Tags** | `tags` | Keywords used for search and filtering in Shopify | textarea, text, select, multiselect | +| **Barcode** | `barcode` | Product barcode or unique identifier for inventory scanning | text | +| **Compare Price** | `compareAtPrice` | The original price — shown as a strikethrough to highlight a discount | price | +| **SEO Title** | `metafields_global_title_tag` | Custom page title used by search engines | text | +| **SEO Description** | `metafields_global_description_tag` | Meta description shown in search engine results | text, textarea | +| **Handle** | `handle` | The URL-friendly slug for the product page (e.g. `blue-running-shoes`) | text | +| **Taxable** | `taxable` | Marks whether tax should be applied to this product | yes/no | +| **Cost per Item** | `cost` | Cost of goods sold (COGS) — used for profit reporting | price | ![Field Mapping Example](./images/export-mapping-fields.png) +> **Warning:** **Handle** must be unique. If several products end up with the same handle, only the **last** one is exported — the rest are silently overwritten. + --- -## Using Fixed Values +## Shopify Status -Sometimes you don't want a field to pull from a UnoPim attribute — you just want every exported product to have the **same value** for that field. That's what the **Fixed Value** option is for. +**Shopify Status** (`status`) is not an attribute mapping — it's a fixed setting. Whatever you choose here is applied to **every product you export**, not to one product at a time. -**Example:** You want all exported products to have a quantity of `100` in Shopify, regardless of what's stored in UnoPim. +| Option | What it does | +|---|---| +| **Active** | The product is ready to sell and can be published to your sales channels | +| **Draft** | The product isn't ready to sell and stays hidden from customers — use this to review products before publishing | +| **Archived** | The product is no longer being sold and isn't available on any sales channel | +| **Unlisted** | The product is active, but customers need a **direct link** to reach it. It won't appear in search, collections, or product recommendations. | -Here's how to do it: +--- -1. Find the **Quantity** field in the mapping list. -2. **Deselect** the UnoPim attribute from the dropdown — the Fixed Value input will become editable once the attribute is cleared. -3. Type `100` in the Fixed Value field. -4. Save your mapping. +## Unit Price -From now on, every product exported to Shopify will have its quantity set to `100` — no matter what value exists in UnoPim. +Some markets (notably the EU) require products to show a **unit price** — the price per standard unit of measure, like "€2.50 per litre". The **Unit Price** section maps the attributes that make this work. -![Fixed Value Example](./images/same-unit.png) +| Field | What it does | What to choose | +|---|---|---| +| **Total amount** | The total quantity contained in the product | A number or decimal type attribute | +| **Total amount unit** | The unit that the total amount is measured in | A text or select type attribute | +| **Base measure** | The reference quantity the unit price is calculated against | A number you type in | +| **Base measure unit** | The unit for the base measure | Select from the dropdown | -> **Tip:** Fixed values are useful for fields like **Taxable**, **Inventory Tracked**, or **Status** where you want a consistent default across your entire catalog. +> **Important:** The value of **Total amount unit** must match a valid Shopify unit — for example `ML`, `CL`, or `L`. Any other value is **not exported**, and the product ends up with no unit price at all. +**Example:** For a 750 ml bottle priced per litre, you'd set **Total amount** to `750`, **Total amount unit** to `ML`, **Base measure** to `1`, and **Base measure unit** to `L`. diff --git a/docs/shopify/collection-attribute-mapping.md b/docs/shopify/collection-attribute-mapping.md new file mode 100644 index 0000000..edf5c8d --- /dev/null +++ b/docs/shopify/collection-attribute-mapping.md @@ -0,0 +1,62 @@ +# Collection Attribute Mapping + +Just like products, UnoPim categories are exported to Shopify as **collections**. Before you can export them, you need to tell the connector which UnoPim attribute maps to which Shopify collection field. This is called **collection mapping** — and you only need to set it up once. + +--- + +## How to Access Collection Mappings + +Click the **Shopify icon** in the left sidebar of your UnoPim dashboard, then click on the **Collection Mappings** tab. + +![Collection Mappings Tab](./images/collection.png) + +On this screen, the left side lists all available Shopify collection fields. For each field, use the dropdown on the right to select the matching UnoPim attribute. + +--- + +## Available Field Mappings + +Here's a breakdown of every Shopify collection field you can map, what it does, and which attribute types it accepts: + +| Shopify Field | Field Code | What it does | Supported attribute types | +|---|---|---|---| +| **Name** | `title` | The collection title shown on your Shopify storefront. This field is required. | text | +| **Description** | `descriptionHtml` | Full collection description — supports HTML formatting | text, textarea | +| **SEO Title** | `seoTitle` | Custom page title used by search engines | text, textarea | +| **SEO Description** | `seoDescription` | Meta description shown in search engine results | text, textarea | +| **Handle** | `handle` | The URL-friendly slug for the collection page. If left empty, the category code is used instead. | text | +| **Collection Type** | `collectionType` | Decides whether the collection is created as a Smart or Manual collection in Shopify | yes/no | +| **Product Sort Order** | `sortOrder` | The order products appear in inside the collection | — (applies to all exported collections) | + +![Collection Field Mapping](./images/collection-attribute.png) + +> **Note:** **Name** is the only mandatory field. The rest are optional — leave any of them unmapped and the connector simply skips that field on export. + +--- + +## Smart vs Manual Collections + +The **Collection Type** field controls how Shopify builds the collection: + +| Mapped value | What Shopify creates | +|---|---| +| **Yes** | A **Smart collection** — a default rule is added automatically | +| **No**, or left unmapped | A **Manual collection** | + +--- + +## Product Sort Order + +**Product Sort Order** is a fixed setting rather than an attribute mapping — whatever you pick here applies to **every collection you export**, not to one collection at a time. + +--- + +## Collection Image Mapping + +At the bottom of the screen you'll find the **Collection Image Mapping** section. Use the **Image Attribute** dropdown to choose which UnoPim attribute holds the collection image. + +![Collection Image Mapping](./images/collection-image-mapping.png) + +Whatever image is stored in the selected attribute is uploaded to Shopify as the collection's banner image when the collection is exported. + +> **Tip:** Leave the **Image Attribute** unmapped if your collections don't need banner images — the collection still exports fine without one. diff --git a/docs/shopify/images/add-definition-fields.png b/docs/shopify/images/add-definition-fields.png index 4926dd2..04d4b36 100644 Binary files a/docs/shopify/images/add-definition-fields.png and b/docs/shopify/images/add-definition-fields.png differ diff --git a/docs/shopify/images/collection-attribute.png b/docs/shopify/images/collection-attribute.png new file mode 100644 index 0000000..10d724e Binary files /dev/null and b/docs/shopify/images/collection-attribute.png differ diff --git a/docs/shopify/images/collection-image-mapping.png b/docs/shopify/images/collection-image-mapping.png new file mode 100644 index 0000000..7e28808 Binary files /dev/null and b/docs/shopify/images/collection-image-mapping.png differ diff --git a/docs/shopify/images/collection.png b/docs/shopify/images/collection.png new file mode 100644 index 0000000..cbb494e Binary files /dev/null and b/docs/shopify/images/collection.png differ diff --git a/docs/shopify/images/edit-cred.png b/docs/shopify/images/edit-cred.png deleted file mode 100644 index afdbd79..0000000 Binary files a/docs/shopify/images/edit-cred.png and /dev/null differ diff --git a/docs/shopify/images/fill-cred.png b/docs/shopify/images/fill-cred.png index 0c470cd..de121fc 100644 Binary files a/docs/shopify/images/fill-cred.png and b/docs/shopify/images/fill-cred.png differ diff --git a/docs/shopify/images/location.png b/docs/shopify/images/location.png new file mode 100644 index 0000000..d8d53f8 Binary files /dev/null and b/docs/shopify/images/location.png differ diff --git a/docs/shopify/images/sales.png b/docs/shopify/images/sales.png new file mode 100644 index 0000000..551cb17 Binary files /dev/null and b/docs/shopify/images/sales.png differ diff --git a/docs/shopify/import-attribute-mapping.md b/docs/shopify/import-attribute-mapping.md index ff35bb6..0ebea84 100644 --- a/docs/shopify/import-attribute-mapping.md +++ b/docs/shopify/import-attribute-mapping.md @@ -16,25 +16,37 @@ On the left side of the screen, you'll see all available Shopify product fields. ## Available Field Mappings -| Shopify Field | Field Code | What it does | +| Shopify Field | Field Code | What it does | Supported attribute types | +|---|---|---|---| +| **Name** | `title` | The product title shown on your Shopify storefront | text | +| **Description** | `descriptionHtml` | Full product description — supports HTML formatting | text, textarea | +| **Price** | `price` | The selling price of the product | price | +| **Weight** | `weight` | Product weight used for shipping calculations | number, metric | +| **Inventory Tracked** | `inventoryTracked` | Indicates whether inventory tracking is enabled | boolean | +| **Allow Purchase Out of Stock** | `inventoryPolicy` | Allows customers to buy the product even when stock is zero | yes/no | +| **Vendor** | `vendor` | The brand or supplier name | text, simple select | +| **Product Type** | `productType` | The category or type the product belongs to | text, simple select | +| **Tags** | `tags` | Keywords used for search and filtering in Shopify | textarea, text, select, multiselect | +| **Barcode** | `barcode` | Product barcode or unique identifier for inventory scanning | text | +| **Compare Price** | `compareAtPrice` | The original price shown as a strikethrough to highlight a discount | price | +| **SEO Title** | `metafields_global_title_tag` | Custom page title used by search engines | text | +| **SEO Description** | `metafields_global_description_tag` | Meta description shown in search engine results | text, textarea | +| **Handle** | `handle` | The URL-friendly slug for the product page (e.g. `blue-running-shoes`) | text | +| **Taxable** | `taxable` | Marks whether tax should be applied to this product | yes/no | +| **Cost per Item** | `cost` | Cost of goods sold (COGS) — used for profit reporting | price | + +--- + +## Unit Price + +Below the field mappings you'll find the **Unit Price** section. This maps the attributes that Shopify uses to show a price per standard unit of measure — like "€2.50 per litre". + +| Field | What it does | What to choose | |---|---|---| -| **Name** | `title` | The product title shown on your Shopify storefront | -| **Description** | `descriptionHtml` | Full product description — supports HTML formatting | -| **Price** | `price` | The selling price of the product | -| **Weight** | `weight` | Product weight used for shipping calculations | -| **Quantity** | `inventoryQuantity` | How many units are available in stock | -| **Inventory Tracked** | `inventoryTracked` | Indicates whether inventory tracking is enabled | -| **Allow Purchase Out of Stock** | `inventoryPolicy` | Allows customers to buy the product even when stock is zero | -| **Vendor** | `vendor` | The brand or supplier name | -| **Product Type** | `productType` | The category or type the product belongs to | -| **Tags** | `tags` | Keywords used for search and filtering in Shopify | -| **Barcode** | `barcode` | Product barcode or unique identifier for inventory scanning | -| **Compare Price** | `compareAtPrice` | The original price shown as a strikethrough to highlight a discount | -| **SEO Title** | `metafields_global_title_tag` | Custom page title used by search engines | -| **SEO Description** | `metafields_global_description_tag` | Meta description shown in search engine results | -| **Handle** | `handle` | The URL-friendly slug for the product page (e.g. `blue-running-shoes`) | -| **Taxable** | `taxable` | Marks whether tax should be applied to this product | -| **Cost per Item** | `cost` | Cost of goods sold (COGS) — used for profit reporting | +| **Total amount** | The total quantity contained in the product | A number or decimal type attribute | +| **Total amount unit** | The unit that the total amount is measured in | A text or select type attribute | + +> **Important:** The value of **Total amount unit** must match a valid Shopify unit — for example `ML`, `CL`, or `L`. Any other value is skipped. --- diff --git a/docs/shopify/index.md b/docs/shopify/index.md index 94fb061..6383d22 100644 --- a/docs/shopify/index.md +++ b/docs/shopify/index.md @@ -58,9 +58,15 @@ Shopify supports **metafields** — custom data fields that go beyond standard p - Weight - Volume - Dimension -- boolean +- Boolean - Date - Number +- Image (file) +- File +- Email +- Link +- Product reference +- Product variant reference These are exported without needing any additional mapping setup. @@ -93,7 +99,7 @@ Before you begin, make sure the following are in place: | Requirement | Detail | |---|---| | **UnoPim Version** | v2.0.0 | -| **Shopify API Version** | 2026-01 | +| **Shopify API Version** | 2026-07 | | **Shopify Plan** | Any plan with Admin API access | | **Shopify Admin Access** | Needed to create a custom app and generate API credentials | | **Terminal / Server Access** | Required to run installation commands | diff --git a/docs/shopify/metafields.md b/docs/shopify/metafields.md index dd34e64..a2cf7ed 100644 --- a/docs/shopify/metafields.md +++ b/docs/shopify/metafields.md @@ -36,14 +36,30 @@ Choose the UnoPim attribute you want to link to this metafield. When a product i ### Type Select the data type for the metafield value. Available options are: -| Type | When to use | -|---|---| -| **Single line text** | Short text values like a material name or colour code | -| **Multi-line text** | Longer descriptions or notes | -| **Color** | Hex colour values | -| **Rating** | Numerical rating values | -| **URL** | Links or reference URLs | -| **JSON** | Structured or complex data | +| Type | Shopify type | When to use | +|---|---|---| +| **Single line text** | `single_line_text_field` | Short text values like a material name or colour code | +| **Multi-line text** | `multi_line_text_field` | Longer descriptions or notes | +| **Color** | `color` | Hex colour values | +| **Rating** | `rating` | Numerical rating values | +| **URL** | `url` | Links or reference URLs | +| **JSON** | `json` | Structured or complex data | +| **Weight** | `weight` | A weight value with its unit — for example `2.5 kg` | +| **Volume** | `volume` | A volume value with its unit — for example `750 ml` | +| **Dimension** | `dimension` | A length value with its unit — for example `30 cm` | +| **Boolean** | `boolean` | A true/false flag — for example "Machine washable" | +| **Date** | `date` | A calendar date — for example a release or expiry date | +| **Number** | `number_integer` / `number_decimal` | A numeric value, whole or decimal | +| **Image (file)** | `file_reference` | An image stored in Shopify's Files — for example a size chart or a care-label graphic | +| **File** | `file_reference` | Any non-image file — for example a PDF spec sheet or a safety datasheet | +| **Email** | `single_line_text_field` | An email address — for example a supplier or warranty contact | +| **Link** | `link` | A text-and-URL pair, so you can store the link label alongside the address | +| **Product reference** | `product_reference` | Points to another product — useful for "goes well with" or replacement-part relationships | +| **Product variant reference** | `variant_reference` | Points to a specific product variant rather than the whole product | + +> **Note on Image vs File:** Shopify stores both as the same underlying type (`file_reference`). The difference is a validation — **Image (file)** restricts uploads to images, while **File** accepts any file type. + +> **Note on Email:** Shopify has no dedicated email metafield type. An email metafield is a `single_line_text_field` with a validation rule that checks the value looks like an email address. --- diff --git a/docs/shopify/setup.md b/docs/shopify/setup.md index 24190aa..e4341c1 100644 --- a/docs/shopify/setup.md +++ b/docs/shopify/setup.md @@ -24,11 +24,11 @@ Fill in the following details: |---|---| | **Shopify URL** | Your Shopify store URL (e.g. `mystore.myshopify.com`) | | **Admin API access token** | The access token you copied from your Shopify app | -| **API Version** | Select `2026-01` | +| **API Version** | Select `2026-07` | ![Credentials Form](./images/fill-cred.png) -> **Note:** The UnoPim Shopify Connector currently supports **API version 2026-01**. Make sure you select this version. +> **Note:** The UnoPim Shopify Connector currently supports **API version 2026-07**. Make sure you select this version. Click **Save** once all fields are filled in. @@ -38,22 +38,29 @@ Click **Save** once all fields are filled in. After saving, you'll be redirected to the credential edit screen. Complete the remaining fields: -![Credential Edit Screen](./images/edit-cred.png) +![Credential Edit Screen](./images/sales.png) **Publishing (Sales Channels)** Select which Shopify sales channels your products should be published to once exported. -**Location List** -Choose the inventory location that will be used when syncing stock quantities. - **Status** Set the default status for exported products — either active or draft. -> **Note:** The **Sales Channels** and **Location List** options are fetched directly from your Shopify store. If you don't see them in the dropdown, make sure they have been created in Shopify first before setting up credentials here. +> **Note:** The **Sales Channels** are fetched directly from your Shopify store. If you don't see them in the dropdown, make sure they have been created in Shopify first before setting up credentials here. + +--- + +## Step 4 — Map Your Locations + +Map a quantity attribute to each Shopify location to send location-wise stock. Any location you leave blank is skipped during sync. + +![Location Mapping](./images/location.png) + +> **Note:** The **Location List** is fetched directly from your Shopify store. If a location is missing from the list, create it in Shopify first. --- -## Step 4 — Map Your Locales +## Step 5 — Map Your Locales If your Shopify store supports multiple languages, all available Shopify locales are fetched automatically. You just need to map each Shopify locale to the corresponding locale in UnoPim. diff --git a/docs/shopify/shopify-setup.md b/docs/shopify/shopify-setup.md index 6ae2c30..bb70bad 100644 --- a/docs/shopify/shopify-setup.md +++ b/docs/shopify/shopify-setup.md @@ -56,19 +56,20 @@ Once the app is created, the version tab will appear. Scroll down and you will f ![Shopify select scopes](./images/select-scopes.png) -You need to enable **read and write** access for the following: - -| # | Scope | Permissions to enable | -|---|-------|-----------------------| -| 1 | Shop locales | `write_locales`, `read_locales` | -| 2 | Fulfillment services | `write_fulfillments`, `read_fulfillments` | -| 3 | Inventory | `write_inventory`, `read_inventory` | -| 4 | Product listings | `write_product_listings`, `read_product_listings` | -| 5 | Products | `write_products`, `read_products` | -| 6 | Translation | `write_translations`, `read_translations` | -| 7 | Sales Channel | `write_channels`, `read_channels` | -| 8 | Location | `write_locations`, `read_locations` | -| 9 | Publications | `write_Publications`, `read_Publications` | +You need to enable **read and write** access for the following. Use the copy button on any row to copy that scope's permissions, or **Copy all** to grab every permission at once. + + ![Shopify select scopes](./images/read-write.png) diff --git a/docs/shopify/sidebar.json b/docs/shopify/sidebar.json index 4c1c9e8..83f95fc 100644 --- a/docs/shopify/sidebar.json +++ b/docs/shopify/sidebar.json @@ -12,6 +12,7 @@ "items": [ { "text": "Setup Unopim Credentials", "link": "/shopify/setup" }, { "text": "Export Attribute Mapping", "link": "/shopify/attribute-mapping" }, + { "text": "Collection Attribute Mapping", "link": "/shopify/collection-attribute-mapping" }, { "text": "Shopify Media & Unit Mapping", "link": "/shopify/media-unit-mapping" }, {"text" : "Import Attribute Mapping", "link": "/shopify/import-attribute-mapping"}, {"text": "Add & Manage Shopify Meta Fields & Definations", "link": "/shopify/metafields"},