> For the complete documentation index, see [llms.txt](https://docs.pyck.cloud/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.pyck.cloud/shopify-app/data-mapping.md).

# What a sync overwrites in pyck

Which fields a sync overwrites in pyck, which it leaves alone, and how files are handled

Audience: Logistics Manager

Every time a product, customer or order changes in Shopify, the app reads the current record from Shopify and updates the matching record in pyck. It changes only what comes from Shopify and leaves everything else on the record as it is.

Everything the app reads from Shopify goes into one field of the pyck record, called `shopify`. Fields you add to your own pyck schemas sit next to it and are filled only if you connect them to a Shopify source.

For example, a customer who has a mapped field `display_name` and a field `storage_zone` that is **Not synced** looks like this in pyck:

```json
{
  "shopify": { "firstName": "Anna", "lastName": "Becker", "...": "..." },
  "display_name": "Anna Becker",
  "storage_zone": "B-12"
}
```

`shopify` is the same whatever you map. A mapped field is an extra copy of a Shopify value, kept in the place you chose. It does not take the value out of `shopify`.

This page explains which fields count as "coming from Shopify", what happens when a value is cleared there, and how you keep a field under pyck's control.

## The rules at a glance

| Field                                                                                                         | Who decides     | What a sync does                                                                 |
| ------------------------------------------------------------------------------------------------------------- | --------------- | -------------------------------------------------------------------------------- |
| The `shopify` field: everything the app reads from Shopify (title, price, vendor, addresses, order totals, …) | Shopify         | Replaces it as a whole. A value Shopify no longer has disappears from it.        |
| A field you mapped to a Shopify source                                                                        | Shopify         | Overwrites it. If the value is cleared in Shopify, the field is removed in pyck. |
| A field set to **Not synced**                                                                                 | pyck            | Never touches it.                                                                |
| A field with no source, or any field your warehouse adds itself                                               | pyck            | Never touches it.                                                                |
| Files (product images, file metafields)                                                                       | Shopify, always | Replaced when the file changes in Shopify, deleted when it is deleted there.     |

In short: **Shopify owns the `shopify` field and what you connected to Shopify. pyck owns everything else. Files always follow Shopify.**

The same rules are shown in the app, in the banner **What a sync overwrites in pyck** when the data mapping is set to **Custom**.

## Where you choose a field's source

Open **Settings**, expand **Advanced** and choose **Configure** next to the connection's **Data mapping**. With **Mapping mode** set to **Custom**, you pick a pyck schema for **Products**, **Customers** and **Orders**, and optionally for **Order lines**. The app lists every field of that schema except `shopify`. For each of those fields you choose where its value comes from:

| Source                                                | Takes the value from                                                        |
| ----------------------------------------------------- | --------------------------------------------------------------------------- |
| **Shopify field**                                     | A built-in Shopify field, such as the product's vendor or the order's total |
| **Shopify metafield**                                 | One of your metafields, for example `custom.color`                          |
| **Product tags** / **Customer tags** / **Order tags** | The record's tags, as a list                                                |
| **Product image** / **Shopify file metafield**        | A file (see [Files](#files) below)                                          |
| **Not synced**                                        | Nowhere. The field is maintained in pyck.                                   |

Choosing a source is a decision about **ownership**, not just about where a value is copied from. Once a field has a Shopify source, Shopify is in charge of it. The value is copied into your field in addition to `shopify`, not instead of it.

A field you leave without a source is **Not synced**. You can save the mapping that way.

Order lines have no metafields or tags in Shopify, so the fields of an order line schema cannot take a source: they are always **Not synced**, and the app writes only `shopify` on order lines.

Your schema must accept the `shopify` field, or the mapping cannot be saved. How to design schemas so that as few fields as possible need mapping is described in [Designing pyck schemas for Shopify](/shopify-app/schema-design.md).

## Fields with a Shopify source

A mapped field always mirrors Shopify.

**Example.** Your product schema has a field `color`, mapped to the metafield `custom.color`.

| In Shopify                               | In pyck after the sync              |
| ---------------------------------------- | ----------------------------------- |
| `custom.color` is set to `blue`          | `color` is `blue`                   |
| You change it to `red`                   | `color` is `red`                    |
| Someone edits `color` to `green` in pyck | The next sync sets it back to `red` |
| You delete the metafield `custom.color`  | `color` is removed from the record  |

Two things follow from this:

* **Changes made in pyck to a mapped field do not last.** The next time the record changes in Shopify, Shopify's value is written again. Make the change in Shopify instead.
* **Clearing a value in Shopify clears it in pyck.** If your warehouse needs the value to stay, the field should not be mapped. Set it to **Not synced**.

A metafield is cleared by deleting it. Some **Shopify fields** work differently: a text field you empty in the Shopify admin may still arrive as empty text, in which case the field stays in pyck with an empty value instead of being removed.

## Fields set to Not synced

A field set to **Not synced** belongs to pyck. The app never writes it and never removes it, whatever happens in Shopify.

Use it for anything your warehouse maintains: a storage zone, a pallet type, a handling note, a unit of measure that only matters on the shop floor.

**Example.** Your product schema has `palletType`, set to **Not synced**. Your team sets it to `EUR` in pyck. You then change the product's title, price and tags in Shopify. After each sync, `palletType` is still `EUR`.

**Switching a field to Not synced keeps its value.** If `ean` was mapped to a metafield and you switch it to **Not synced**, the value already in pyck stays, even if you later delete the metafield in Shopify. From then on, pyck owns it.

## Fields with no source, and your own fields

Fields with no source are **Not synced**: the app leaves them alone. This is also what happens when your pyck schema gains a new field that has not been mapped yet.

The same goes for anything your warehouse writes to a record that has no Shopify source. A workflow that stamps an order with a `status` or a hold reason keeps that value through every later order update from Shopify, as long as that field is not mapped to a Shopify source.

## The shopify field

Everything the app reads from Shopify (title, price, vendor, weight, addresses, order totals and so on) is written into one field of the record, `shopify`, under Shopify's own names, for example `shopify.product.title` or `shopify.shippingAddress.city`. It is owned by Shopify, whatever your mapping says.

On every sync the whole `shopify` field is replaced with what Shopify has now. A value Shopify no longer has is simply not in it any more. A note deleted on an order in Shopify, for example, disappears from the order in pyck.

Do not put warehouse information into `shopify`, and do not edit it in pyck: the next sync replaces it. Add a field of your own to the pyck schema and leave it **Not synced**.

## Files

Files are the one exception to "only what you mapped". **A file always follows Shopify**, whether you mapped it or not:

| In Shopify                                                               | In pyck after the sync                                                                                                              |
| ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |
| You attach a file to a file metafield (e.g. an Amazon label on an order) | The file is attached to the record                                                                                                  |
| The same order syncs again with nothing changed                          | Still one file, no duplicates                                                                                                       |
| You swap the file for a new one                                          | The new file is attached and the old one is deleted                                                                                 |
| You clear the file metafield                                             | The file is deleted from the record                                                                                                 |
| You add an image to a product                                            | It is attached to the items of the variants it is assigned to in Shopify, or to every item of the product if it is assigned to none |
| You remove an image from a product                                       | The image is deleted from the item                                                                                                  |

Files your team attaches in pyck directly are never deleted by the app, even when Shopify's files change. The app only removes files it delivered itself. You recognise those by their description: `Shopify metafield <namespace.key>`, for example `Shopify metafield custom.amazon_labels`.

Single image files are supported. Other file types in a file metafield, such as PDFs, and metafields holding a list of files are not delivered yet. Files that were never delivered are not deleted either.

## When Shopify cannot be read

Shopify only tells the app *which* record changed. The app then reads the record from Shopify before it writes anything.

If that read fails, for example because Shopify is briefly unavailable or rate-limits the request, **nothing is written** and Activity shows a failed entry. The record in pyck stays exactly as it was, and the next change or a **Sync now** brings it up to date. If the record was deleted in Shopify before the app could read it, the sync is skipped with the reason "No longer exists in Shopify".

The same holds for fields with a Shopify source, for metafields in Auto mode and for files, which the app reads separately: if one of them cannot be read, it is **not** treated as cleared. The field or file stays exactly as it is in pyck, and the next successful sync brings it up to date.

A **metafield definition that no longer exists** is different. You pick metafields from a list, but if a definition is later deleted or renamed in Shopify, the mapping still names the old one and **Data mapping** marks it **Not defined in Shopify**. Shopify then answers normally and reports no such metafield on the record, so the app treats that as an empty value and **removes the field in pyck**. After deleting or renaming a metafield definition in Shopify, update the mapping before the next sync.

## Choosing between a Shopify source and Not synced

Ask who should be able to change the value.

| If                                                                                            | Then                                                                                                       |
| --------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| The value is maintained in the Shopify admin, and pyck should always show what the shop shows | Give it a Shopify source                                                                                   |
| The value is maintained by the warehouse, or set by a pyck workflow                           | Set it to **Not synced**                                                                                   |
| Both sides need to edit it                                                                    | Pick one owner. Edits on the other side are overwritten (Shopify source) or never reach pyck (Not synced). |

## Values pyck rejects

A mapped value is converted to the type your schema gives the field (a number, true or false, or text) and then has to fit it. If your schema only allows three characters and the Shopify source sends `POUNDS`, or expects a single value and the source sends a list of tags, pyck rejects the whole record. Nothing on it is updated, not even the fields that would have fit.

The same happens when your schema marks a mapped field as **required** and the value is cleared in Shopify: the app removes the field, pyck refuses a record without it, and the record stops updating until Shopify has a value again. Map required fields only to sources that are always filled, or set them to **Not synced**.

**Activity** shows a failed entry naming the field for orders, customers, new products and every record a **Sync now** run touches. When an existing product is updated because it changed in Shopify, a rejection only appears there after you choose **Record every attempt** on the Activity page.

**What to do.** Map the field to a source whose values fit, or set it to **Not synced**. For example, a product's **Weight unit** is not a unit of measure like `PCS`, and **Order tags** always arrive as a list.

A schema that does not accept the `shopify` field would make every sync fail. Data mapping refuses to save it and says which schema needs `"shopify": { "type": "object" }` added.

## Connections in Auto mode

With **Mapping mode** set to **Auto**, there is no per-field mapping: the app fills its standard Shopify schemas, and the record carries only `shopify`. To bring your own metafields along, use **Check** in the **Shopify metafields** block of **Data mapping** and then **Add these to my schemas**. Their values arrive inside `shopify`, under `shopify.metafields`, for example `shopify.metafields.custom.material`. They follow Shopify and disappear in pyck when the metafield is deleted in Shopify. File metafields are not added to the schemas: they are attached to the record as files, and follow Shopify here too.

## Related pages

* [Setup](/shopify-app/setup.md): connecting your first tenant.
* [Sending data to several pyck tenants](/shopify-app/routing.md): which tenant receives what.
* [When something looks wrong](/shopify-app/troubleshooting.md): symptoms and what they mean.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.pyck.cloud/shopify-app/data-mapping.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
