# Shopify variant options to size and color

Shopify stores variant options positionally as option1, option2 and option3 with whatever names the merchant typed, while feeds expect named attributes such as size and color. The mapping has to read the option by its name rather than its position, because the order differs from one product to the next.

- **Canonical URL:** https://www.feedlab.io/knowledge/mappings/shopify-variant-options-to-size-and-color
- **Last reviewed:** 18 September 2026
- **Source:** feedlab knowledge base
- **Licence:** free to quote and cite with attribution to feedlab


## The Shopify side

| Property | Value |
| --- | --- |
| API field | `variant.option1 / option2 / option3` |
| Called | Variant options |
| Found at | Product → Variants → Options (the option names and values you define per product) |


## Before and after

| In Shopify | In the feed | Note |
| --- | --- | --- |
| `option1 "Size" = M, option2 "Colour" = Black` | `size M, color Black` | Read by name, so the position does not matter. |
| `option1 "Color" = Pewter` | `color Grey` | Normalised for filtering. Pewter stays in the title. |
| `option1 "Shade" = 220 Natural` | `color Beige` | Cosmetics: shade recognised as a colour option through its alias and normalised. |
| `option1 "Size" = EU 40` | `size EU 40, size_system EU` | The system stated separately rather than left inside the size value. |
| `option1 "Flavour" = Vanilla` | `(no attribute)` | No feed equivalent. Carried in the title, and in a custom label if useful. |
| `option1 "Title" = Default Title` | `(no attribute)` | Shopify's placeholder for a product with no real options. Must never reach the feed. |



## The transformation, step by step

1. **Read the option names, not the positions** — One product has Size as option1 and Colour as option2; the next has them the other way round. Mapping by position works on the product you tested and fails on the rest of the catalogue, and the failure looks like random mis-mapped values.
2. **Normalise the option names** — Colour, Color, Shade, Finish and Metal all mean the same target attribute. Match case-insensitively against a list of known aliases per attribute, and keep the list somewhere you can extend, because a new product introduces a new spelling eventually.
3. **Normalise the values, keeping the original for the title** — Send a recognisable value for filtering, so grey rather than Pewter and M rather than M/L. Keep the merchant's own wording in the title, where shoppers search for it. Both versions have a job, and neither can do the other's.
4. **Handle the options with no feed equivalent** — Length, capacity, flavour and scent are real variant options with no matching attribute. They belong in the title so the row is distinguishable, and in a custom label if you want to segment on them.
5. **Send one value per attribute** — Feeds take a single size and a single colour per item. A product varying by both needs each combination as its own row, which is what the variant-level structure already gives you.



## What goes wrong

### Default Title leaks into feeds

A product with no options still has one variant, and Shopify names its option value "Default Title". Any mapping that blindly appends option values to the title produces "Oxford Shirt - Default Title", which is visible to every shopper and appears across whole catalogues.

### Position-based mapping fails silently

Mapping option1 to size puts a colour in the size attribute on every product where the merchant created colour first. The feed validates, the values are plausible, and the filters are wrong.

### Size values are inconsistent within one catalogue

The same store carries M, Medium, 10, UK 10 and 40 in its size options, sometimes across products in one collection. Channels accept any of them, so nothing is reported, but grouping and filtering only work when one convention is used.

### Marketing colour names are not filterable

Midnight, Oatmeal and Sand tell a shopper nothing a filter can use. Sending only the marketing name removes the item from colour filtering altogether, which is the single most used filter in apparel.




## How feedlab maps it

feedlab matches each variant option by name against a list of aliases per target attribute, normalises the value for filtering while keeping the original available for the title, and ignores Shopify's Default Title placeholder. Options with no feed equivalent can be routed into the title or a custom label explicitly rather than being dropped.






## Frequently asked questions

### How do I map Shopify variant options to size and colour?

By reading the option name rather than its position. Shopify stores options as option1, option2 and option3 in whatever order the merchant created them, so position two is size on one product and colour on the next.

### Why does "Default Title" appear in my feed?

It is the option value Shopify gives the single variant of a product with no real options. Mappings that append option values to the title carry it through, and it needs excluding explicitly.

### Should I send the marketing colour name or a plain colour?

A plain colour in the colour attribute so filtering works, with the marketing name kept in the title where shoppers search for it. Sending only the marketing name removes the item from colour filters.

### What do I do with options like flavour or capacity?

There is no matching feed attribute, so put them in the title to keep each row distinguishable, and in a custom label if you want to segment or bid on them.




## Primary sources

- [Google: Apparel and accessories attributes](https://support.google.com/merchants/answer/6324492)
- [Shopify: ProductVariant API reference](https://shopify.dev/docs/api/admin-graphql/latest/objects/ProductVariant)



