Shopify — integration guide
DPP Agent is installed from the Shopify App Store and reads your catalogue
through Shopify's GraphQL Admin API, version 2026-10. It never uses
the REST Admin API, and it never writes to your store. One passport is
created per product variant.
What the app does, in one sentence
DPP Agent pages through your products with the GraphQL products query,
turns every variant into a draft passport, addressed by its barcode when
the barcode is a GTIN and by its SKU when it is not, and ingests it through
the same conflict-aware pipeline as every other integration.
Install and authorisation
The app uses Shopify's managed installation:
- The merchant installs DPP Agent from the Shopify App Store.
- Shopify shows the access the app asks for (see the scopes below) and the merchant approves it. Shopify, not DPP Agent, runs this consent screen.
- When the app opens inside the Shopify admin, it exchanges Shopify's session token for an offline access token (token exchange). The token expires and is renewed automatically before each sync.
- The token is encrypted at rest (AES-256-GCM), decrypted only in memory, and never logged or shown in the UI.
There is no separate OAuth "code" flow and no access token to paste.
Access scopes
All read-only:
| Scope | Why |
|---|---|
read_products |
Products, variants, images, product video, metafields |
read_inventory |
Whether a variant ships, and its country of origin |
read_translations |
Product titles and descriptions in your other languages |
read_locales |
Which languages your store publishes |
read_markets |
Which countries you sell to, so we can tell whether EU rules apply |
read_metaobjects |
The values of Shopify's category metafields (colour, fabric, target gender, age group, care instructions…), which are stored as metaobjects |
read_metaobjects was added in October 2026. A store that installed
before then is asked to approve it the next time the app is opened in the
Shopify admin. Until the store approves it, sync still runs; the category
metafields are kept as references and not mapped.
No customer, order or draft-order data is requested. No write scope is requested.
How a variant gets its address
| The variant has… | Passport address |
|---|---|
| a barcode that is a GTIN | /01/<gtin> (GS1 Digital Link) |
| a barcode that is not a GTIN, and a SKU | /products/<sku> |
| no barcode, and a SKU | /products/<sku> |
| neither a GTIN nor a SKU | no passport |
A barcode counts as a GTIN only when it is 8, 12, 13 or 14 digits, its GS1
check digit computes, and its prefix is one GS1 issues for trade items
(not an in-store, coupon or demonstration prefix). A barcode that fails is
kept on the passport as shopify.raw.barcode, so you can see why the
passport is on /products/.
DPP Agent never makes up a GTIN. Add the real barcode in Shopify and sync
again to move a variant to /01/<gtin>. The sync result counts each case:
passports_gtin, passports_sku, barcodes_not_gtin,
variants_without_barcode and variants_without_address.
What is read, and where it lands
| Passport field | Shopify source |
|---|---|
| GTIN / address | variant.barcode (see above), else variant.sku |
espr.pid.product_name |
product.title (+ translations) |
espr.pid.product_description |
product.descriptionHtml, HTML removed, first 600 characters (+ translations) |
espr.pid.color |
the variant option named Colour (or Color, Färg, Farbe…); else the product's shopify.color-pattern when it has exactly one value |
espr.pid.size |
the variant option named Size (or Storlek, Größe, Taille…) |
tex.pid.model_number |
variant.sku |
tex.product.brand_category |
product.productType (+ translations) |
tex.product.hero_image_url, tex.product.gallery |
product media images, the variant's own image first |
tex.product.video |
the product's video (the MP4 nearest 720p) |
tex.mfg.country_of_origin |
variant.inventoryItem.countryCodeOfOrigin |
tex.pid.target_group |
shopify.target-gender + shopify.age-group (see below) |
espr.care.instructions |
shopify.care-instructions, when every value is an instruction |
ict.energy.class |
shopify.energy-efficiency-class, classes A–G only |
Options are matched by their name, not their position. An option whose name
is not recognised is kept in shopify.raw.options.
Shopify's category metafields
Shopify's standard product taxonomy gives each category a set of attributes that merchants fill in under Category metafields. DPP Agent maps one to a passport field only where the meaning is the same, and decides on Shopify's taxonomy value, not on the label you see (which you can rename):
- Target group: Female + Adults → women, Male + Adults → men, Unisex + Adults → unisex, Female + Kids → girls, Male + Kids → boys, Babies / Newborn / 0–6 months / 6–12 months → babies. Other combinations (for example Teens, Toddlers, or Unisex + Kids) are not mapped.
- Colour: only when the product has a single colour value; otherwise the variant's Colour option is used.
- Care instructions: Machine washable, Hand wash, Dry clean only, Tumble dry, Dryer safe, in your own wording. "Ironing instructions" and "Other" are not instructions, so a set containing them is not mapped.
- Energy efficiency class: A to G. A+, A++ and A+++ belong to the old scale and are not mapped.
Every category metafield, mapped or not, is kept on the passport under
shopify.raw.category_metafields with its labels, its taxonomy values and
the field it was mapped to (null when it was not). Fabric, material,
pattern, size, recycled content, certifications and the rest are kept there
for you to confirm in a later release; they are not written to the
passport's material composition, because a fabric name is not a fibre
composition with percentages.
Your own metafields
Metafields in your own namespaces (for example custom.*) are read and
kept on the passport under shopify.raw.metafields with their type and
value, marked with Shopify as the source. They are not written to any
passport field. A screen for choosing where each one goes is planned.
What Shopify does not hold
Shopify has no place for fibre composition with percentages, the manufacturer, substances of concern, certificates, repair or end-of-life information. Add these in DPP Agent, upload a document, or connect a supplier system such as Delogue or TrusTrace alongside.
Settings reference
| Setting | Required | Purpose |
|---|---|---|
shop_domain |
yes | <your-shop>.myshopify.com, set at install |
product_status |
no | Default active. draft, archived or any for a one-off pull |
exclude_product_types |
no | Extra product types never to make passports for |
The API version is not a setting. Every call uses the version DPP Agent is
built and tested against (2026-10 today); it is raised for all stores at
once.
Sync semantics
- Sync runs from an hourly scheduler, at the interval set per connection (default every 6 hours), and on demand from the integration page.
- Products are read a few at a time, with cursor pagination; the page shrinks automatically if Shopify reports a query is over its cost limit, and the sync waits when Shopify asks it to (throttling).
- Draft passports are updated. A published passport gets a pending revision for a person to review. Withdrawn, archived and recalled passports are left alone.
- A product removed from Shopify keeps its passport (EN 18219 / EN 18223 retention).
Uninstall
Uninstalling the app stops sync immediately and clears the access token.
The passports stay until Shopify sends shop/redact (48 hours after
uninstall), which deletes the store's data in DPP Agent.
Troubleshooting
- HTTP 401 on sync — the app was uninstalled, or the authorisation could not be renewed. Open DPP Agent from the Shopify admin to renew it.
metaobjects: no_scopein the sync result — the store has not approvedread_metaobjectsyet. Open the app in the Shopify admin and approve the updated access.- Many passports on
/products/— the variants have no barcode, or a barcode that is not a GTIN. Fill in the barcode in Shopify and sync again. - A variant has no passport — it has neither a GTIN barcode nor a SKU.
- Empty catalogue — all products are draft or archived while
product_statusisactive.
Open a ticket at support@dppagent.com with the integration ID and the
sync log.