Skip to content
SyncMyShop

Integrations

Product data: defined once, correct in every channel

The ERP knows the item number, the barcode and the weight. The PIM or the store knows the title, the images and the description. A product page needs both, grouped into one product with the right variants. We build that integration to your data model, host it and run it.

Which system owns which field?

Ownership is set per field, not per system. A product record in the store is assembled from two or three sources, and every field has one of them as its owner.

Field Owner Direction When it has to arrive
SKU, variant structure, item status ERP to the PIM and the store before the item can be sold
UPC or GTIN, weight, dimensions, HS code ERP to the store with the item, and on change
Title, description, attributes, images PIM, or the store when there is no PIM to the store, or stays in the store when the content is approved
Categories and navigation store stays in the store never synced
Translations PIM to the store, per locale when the locale is complete

The failure this prevents has a fixed pattern. ERP item 20731-BLK-048 carries the description TSHIRT CREW BLK 048, written for a pick list. An integration that maps the ERP description to the store title replaces "Crew-neck T-shirt" with that string on every run. The merchandising team retypes it until someone switches the product sync off.

The rule that holds: the ERP publishes identifiers, units, status and basic commercial data. Content stays with the PIM or the store, and the integration has no write path from the ERP to those fields. When two sources deliver a value for the same field, the owner's value is written and the other one is logged as a difference.

Product data is one of the five flows on the integrations overview.

Three layers between the ERP and the product page

Product data passes through three models, and each has its own job.

  1. Operational data, in the ERP. One item per thing that is bought, stocked and picked, with internal codes such as BLK and 048.
  2. Commerce data, in the PIM or the integration. Which items form one product, what the options are called, which values a buyer sees.
  3. Customer experience, in the store. The product page, the swatches, the size picker and the navigation.

A limit of one layer should not reach the next. A T-shirt in 4 colors and 6 sizes is 4 times 6: 24 items in the ERP. Exported one to one, the store gets 24 products with one variant each. An ERP that keeps one item per color with a size run gives 4 products. In both cases a shopper looking at black cannot switch to navy, and a search for the shirt returns 4 or 24 results for one style. Grouped in the commerce layer, the same 24 items are 1 product with 2 options and 24 variants.

Three layers between the ERP item and the product page One T-shirt in 4 colors and 6 sizes is 24 items in the ERP, each with internal codes such as BLK and 048. The integration groups them under style 20731 and translates the codes. The store shows 1 product with 2 options and 24 variants. from ERP to product page 20731-BLK-048 Operational data: ERP 24 items, internal codes 20731 / Black / 48 Commerce data: integration Grouped by style, codes translated 1 product, 24 variants Customer experience: store One page, swatches, size picker 4 colors times 6 sizes is 24 ERP items. Exported one to one they are 24 products in the store. Grouped on style 20731 they are 1 product with the options Color and Size.
One T-shirt in 4 colors and 6 sizes: 24 items in the ERP, 1 product with 24 variants in the store.

The grouping needs a key. With a matrix parent in the ERP, the parent is the key. Without one, it is a style number in a custom field or a fixed part of the item number: 20731-BLK-048 splits into style 20731, color BLK and size 048.

The codes then go through a translation table: BLK becomes Black, NVY becomes Navy, 048 becomes 48. That table is state, and someone has to own it. A color code that is missing from the table holds the product back and puts it on the run report. The alternative is a swatch on the product page labeled OLV.

What actually moves

No black box: these are the fields in a product flow, with what happens to each on the way.

Field Example What is done with it
SKU 20731-BLK-048 matching key, kept as text; Shopify treats it as case-sensitive
Parent or style 20731 groups items into one product
Barcode 850012345671 kept as text, check digit validated
Option values BLK, 048 translated to Black, 48
Status active, inactive mapped to ACTIVE, DRAFT or ARCHIVED
Weight 0.45 lb value and unit, converted when the target uses another unit
Title and description from the PIM, per locale HTML reduced to the tags the theme renders
Images URL, position, alt text main image first, compared by content and not by filename
Attributes material: 100% cotton written to metafields; the definition has to exist in the store

On Shopify the whole product is written with one productSet call, documented in Shopify's productSet reference:

{
  "identifier": { "handle": "crew-neck-t-shirt-20731" },
  "input": {
    "title": "Crew-neck T-shirt",
    "status": "ACTIVE",
    "productOptions": [
      { "name": "Color", "values": [{ "name": "Black" }, { "name": "Navy" }] },
      { "name": "Size", "values": [{ "name": "48" }, { "name": "50" }] }
    ],
    "variants": [
      {
        "sku": "20731-BLK-048",
        "barcodes": [{ "value": "850012345671" }],
        "optionValues": [
          { "optionName": "Color", "name": "Black" },
          { "optionName": "Size", "name": "48" }
        ]
      }
    ]
  }
}

The fragment shows one variant of the 24. The call behaves differently per field type. For plain fields it updates what is sent and leaves the rest alone. For list fields, which include variants, metafields and collections, it creates and updates what is sent and deletes what is not. A call that carries 23 of the 24 variants removes the twenty-fourth from the store.

A NetSuite matrix child item mapped to a Shopify variant The item ID becomes the variant SKU, the UPC code becomes a barcode stored as text, the parent selects the product, and the color and size codes become option values through a translation table. The ERP sales description is not mapped and the product title comes from the PIM. NetSuite item (matrix child) Shopify productSet input parent 20731 itemid 20731-BLK-048 upccode 850012345671 custitem_color BLK custitem_size 048 salesdescription TSHIRT CREW BLK 048 not mapped identifier.handle crew-neck-t-shirt-20731 variants[].sku 20731-BLK-048 variants[].barcodes 850012345671 text, check digit validated optionValues: Color Black optionValues: Size 48 title Crew-neck T-shirt owned by the PIM groups 24 items lookup table lookup table
Where each field of an ERP item lands on a Shopify variant, and the two fields that are deliberately not connected.

The source in the diagram is a NetSuite matrix child item. itemid, upccode, parent and salesdescription are standard fields. custitem_color and custitem_size are custom fields, and their names differ per account, so the mapping starts with a list of the fields your ERP has.

Variants: matrix items, configurable products and options

Every system models "one product, several versions" in its own way, and each has a ceiling.

System Parent Child Ceiling
Shopify product variant 3 options and 2,048 variants per product
NetSuite matrix parent item subitem 2,000 combinations of matrix options
Adobe Commerce configurable product simple product with its own SKU set by the attributes used for variation
Akeneo product model variant product set by the family variant

The ceilings decide the mapping before any field is touched. Work pants in 12 colors, 9 waist sizes and 20 lengths are 12 times 9 times 20: 2,160 combinations. That is 112 over Shopify's limit and 160 over NetSuite's. The style is split into two products, by fit or by color group, and the split is a rule in the integration so both systems agree on it.

A fourth option has the same effect. Color, waist, length and fit are four options against Shopify's three. Either two of them are merged into one option ("32 x 34"), or fit becomes the product level.

SKUs have to be unique across the whole catalog, not per product. A configurable product in Adobe Commerce is built from simple products that each carry their own SKU. A size code used as a SKU, such as 048 under two styles, cannot exist twice: the second style's child is rejected or lands on the first style's record. The variants page covers grouping keys, split rules and option order.

Identifiers: SKU, UPC and GTIN

A SKU is your own code. A GTIN is assigned under a GS1 company prefix, and it comes in four lengths: GTIN-8, GTIN-12 (the UPC), GTIN-13 (the EAN) and GTIN-14 (cases and inner packs). The last digit of each is a check digit. From the right, the digits before it are multiplied by 3 and 1 in turn, and the check digit brings the sum up to the next multiple of ten. The method is on GS1's check digit page.

UPC without check digit    8 5 0 0 1 2 3 4 5 6 7
multiply by                3 1 3 1 3 1 3 1 3 1 3
result                     24+5+0+0+3+2+9+4+15+6+21 = 89
check digit                90 - 89 = 1
GTIN-12 (UPC)              850012345671
GTIN-13                    0850012345671
as 14 digits               00850012345671
case of 12, indicator 1    1085001234567 + check digit 8 = 10850012345678

Three things follow from this.

Padding does not change the number. 850012345671, 0850012345671 and 00850012345671 are the same GTIN. As strings they are three different values, and a match on string equality misses two of them. The integration compares identifiers on a normalized form: 14 digits, right justified, filled with zeros on the left.

A case has its own GTIN. The case of 12 above ends in 8, not in 1. A feed that lists the case GTIN on the unit item sells a single shirt under the barcode of a box. Shopify accepts up to 20 barcodes per variant, so a unit and its case can both be stored where the store needs them.

Spreadsheets damage identifiers. Excel removes leading zeros and shows a long number in scientific notation. A supplier's 00123456 becomes 123456, and 850012345671 becomes 8.50012E+11. A barcode that is too short or fails its check digit on import is the usual sign that a file went through a spreadsheet. Such rows are listed with the reason and are not written. The note on SKU, UPC and GTIN goes through each number type.

What goes wrong quietly

Failure What you see How it is handled
ERP description mapped to the title titles change back to TSHIRT CREW BLK 048 overnight no write path from the ERP to content fields
A list sent incomplete a variant, a metafield or a collection link disappears every list is sent complete, and a run that would remove variants is held
Wrong character set Café table arrives as Café table encoding set per source, UTF-8 and Windows-1252 told apart before parsing
Supplier reuses an image filename the old photo stays, or a new photo lands on the wrong product images compared by content hash
Attribute missing in the target the value is dropped and no error is raised unmapped attributes listed per run
Missing translation an empty title in one store language rule per locale: hold back or use the fallback language
Paging past 10,000 products beyond the ten-thousandth never arrive cursor paging on large collections

The last row is specific and easy to miss. Akeneo's REST API returns at most 100 items per page, and its offset paging stops at the ten-thousandth item with HTTP 422. An integration built and tested against a pilot catalog of 8,000 products works. At 10,001 products it stops reading, and the newest products are the ones that go missing. Collections of that size are read with the search_after cursor instead.

Records that fail validation go on a list with the SKU and the reason. They are not skipped silently. The note on field mapping describes the classes of mismatch, and what not to sync lists the fields that are better left with their owner.

Throughput and limits

System Limit Number
Shopify variants and options per product 2,048 and 3
Shopify, stores with 500,000 variants or more new variants per day 10,000, no limit on Plus
Shopify GraphQL Admin API points restored per second 100 standard, 200 Advanced, 1,000 Plus
Shopify bulk mutation JSONL upload 100 MB, done within 24 hours
Shopify product images file size and resolution under 20 MB, at most 25 megapixels
Akeneo REST API requests 100 a second per PIM instance, 4 at once per connection
Akeneo REST API items per page 100
NetSuite matrix option combinations 2,000 per parent

Sources: Shopify API limits, Shopify's help center and Akeneo's REST API documentation, checked on October 3, 2026.

A worked example: a catalog of 4,000 styles with 36,000 variants, from Akeneo to Shopify.

Reading it is 4,000 product models and 36,000 variant products at 100 per page: 40 plus 360 is 400 requests. At 4 requests at once that is a matter of minutes.

Writing it is 4,000 productSet calls, one per product with its variants. A mutation costs at least 10 points, and a standard plan restores 100 points a second, so the ceiling is 10 calls a second: 4,000 divided by 10 is 400 seconds, just under 7 minutes at the minimum cost. Shopify returns the actual cost of each call in the response, and the queue paces on that number. For a first load the same input goes up as a JSONL file through a bulk operation. Shopify does not count a bulk operation against the rate limit, so the regular budget stays free for stock and orders.

After the first load only changes are sent. If 180 products changed since the last run, that is 180 calls: 18 seconds.

Images are the slow part. 4,000 products with 5 images each are 20,000 files, and Shopify fetches each one from the URL it is given. A file of 20 MB or more, or above 25 megapixels, is refused. The integration checks size and dimensions first and lists the files that need a smaller export.

A new season on a large store hits a different limit. A store on a standard plan that already holds 500,000 variants can add 10,000 a day. A season of 36,000 new variants takes 36,000 divided by 10,000: 4 days, so the load starts 4 days before the launch date. The notes on Shopify API rate limits and integration throughput work through the cost model.

You stay in control

Every run is compared with the current state of the store before anything is written.

  • Dry run. The integration reads the ERP and the PIM, builds every product and writes nothing. You see which products it would create, change or archive.
  • Approval. New products can wait as drafts until someone approves them, while changes to existing products go through.
  • Exclusions. A product, or one field of a product, is left out. A title written for a campaign stays as it is.
  • Overrides. A value pinned for one product with an end date, such as a temporary title during a promotion.
  • Diff per run. Which products changed, which field, from which value to which, and from which source.

A run that would remove variants or archive a large share of the catalog is held:

run 2026-10-02 02:00   source: PIM and ERP   products: 4,000
changed: 182   new: 14   unchanged: 3,804
held: 6 products would lose 1 or more variants
  20731  variants 24 -> 23   missing in source: 20731-BLK-048
action: waiting for release

In this run the ERP item was set to inactive by mistake. Released as it stands, the run removes the variant from the product page. Corrected in the ERP, the next run shows 24 of 24 and nothing is held. The dry run and approval page describes the controls.

In depth

Product data connects to the other flows. The variant created here is the record that stock and availability writes quantities to and that pricing and customer terms writes prices to. An order line in orders, customers and shipping points back to the same SKU. A SKU that changes in the ERP without the integration knowing breaks all three.

Systems and platforms

PIM systems. Akeneo and Salsify. A PIM delivers content per locale and per channel, so the integration selects one channel and one locale per store and maps attributes to store fields and metafields.

ERP systems. NetSuite, Business Central, SAP Business One and Acumatica. In NetSuite a matrix parent holds at most 2,000 option combinations, and the UPC sits in the upccode field of the item.

Store platforms. Shopify, Magento, WooCommerce and BigCommerce. Shopify takes 3 options and 2,048 variants per product. Adobe Commerce builds a configurable product from simple products, each with its own SKU.

Combinations. Shopify and NetSuite and Magento and NetSuite have their own pages. Apparel catalogs, where the color and size grid is the main mapping problem, are covered under apparel and footwear.

A system that is not listed can be integrated when its product data can be read in a controlled way: an API, a database view, or a scheduled export file. Tell us what you run.

Frequently asked questions

Do we need a PIM to sync product data to the store?

No. Without a PIM the ERP owns identifiers, status, weight and variant structure, and the store owns titles, descriptions and images. The integration writes the first group and has no write path to the second. A PIM becomes useful when the same content has to reach several stores, languages or marketplaces, because then the content needs one owner outside any single store.

Which system should own product descriptions and images?

The system where the people who write them work: the PIM when there is one, the store when there is not. The ERP description is written for purchasing and picking and is rarely fit for a product page. The integration can copy it once as a first draft for new products and never touch the field again.

What happens to a change someone makes directly in the store admin?

That depends on the owner of the field. A change to a field the store owns stays. A change to a field the ERP or PIM owns is replaced on the next run, and the run diff shows the value that was replaced. A product with a manual arrangement can be excluded, per product or per field.

Our ERP has no parent items. Can colors and sizes still become variants?

Yes. The grouping key can be a style number in a custom field or a fixed part of the item number: 20731-BLK-048 gives style 20731, color BLK and size 048. Items without a recognizable key go on a list to be assigned by hand once, and the assignment is kept. The variants page covers the grouping rules.

Does the integration delete products that are removed from the ERP?

Only when you set that rule. An inactive or deleted ERP item can set the product to draft, archive it, or leave it alone, and the choice is made per connection. Deleting is the one action the next run cannot undo, so the default is to archive and report it in the run diff.

How fast does a product change reach the store?

Status changes and new items that are ready to sell go out within minutes, as events. Content and attributes go in a scheduled run of changed products, hourly or a few times a day, and the full catalog is compared once a night. Product data changes less often than stock, so it gets a smaller share of the API budget.

Can one product record feed several stores and languages?

Yes. Each store or channel gets its own selection of products, its own locale and its own mapping of attributes. A translation that is missing in the PIM is handled by a rule per locale: hold the product back for that store, or publish it in the fallback language. Held products are listed in the run report.

What if some items have no UPC or GTIN?

The product is still synced, with the barcode left empty and the item on a list. An invented or reused barcode is worse than none: a number with a wrong check digit fails validation in every system that checks it, and a reused number points to a different product. The note on SKU, UPC and GTIN explains the number families.

Tell us what you need

Tell us which systems you use and what needs to work better. We reply personally within one working day. We help you define the work, then agree the price and timing before you commit.

  • You know the price and the timeline before you commit to anything
  • We work out the connection that takes the work off your hands
  • We handle the build, hosting, monitoring and maintenance
  • Your team has less information to retype and fewer discrepancies to chase

Suppliers, products, orders per day, a rough estimate is fine.

Or email directly: carsten@syncmyshop.com