---
title: "Who owns which field: the store, the ERP, or the PIM"
description: "Stock is the easy field. Price, attributes, media, alt text, per-locale copy and URL keys are the ones two systems both write, and the ownership rule is limited by what your platform can express."
author: "Luboš Zápotočný"
published: "2026-08-06"
language: "en"
canonical: "https://zapolu.com/blog/product-data-ownership/"
---

# Who owns which field: the store, the ERP, or the PIM

Every store that connects an ERP eventually settles who owns the
stock number. The answer is
[almost always the ERP or the warehouse system](/blog/erp-eshop-stock-mismatch/),
because that is where goods are booked and where they physically
move, and once that is written down the synchronization bugs become
mechanical.

Then the same question arrives for every other field, and the tidy
answer stops working. Stock is one number with one meaning. Price is
one number per website, or per market, or per customer company.
Product copy is one value per language. An image is one file, but its
alt text is a sentence per language. Nobody argues about who owns
stock for long. The rest of the record is where the ownership
question stays open.

This post gives a field-by-field ownership rule for prices,
attributes, media, per-locale copy, B2B pricing and URL keys, then
checks each rule against what Magento and Shopify can actually
express, where the ERPs used in Central Europe stop, and when a PIM
earns its place. The platform half is Magento and Shopify; a Czech or
Slovak store is at least as likely to be on Shoptet, and the
field-ownership question there is the same even though the mechanisms
are not. Every vendor fact was checked against the vendor's
own documentation on August 4, 2026, and the load-bearing ones carry
their link; where something could not be verified, we say so.

## One owner per field, at one scope

The principle from the stock post still holds: one system of record
per fact. What changes is that a field is not a fact until you have
also named its scope. "The ERP owns price" is not a rule an
integration can implement. "The ERP owns list price per website, and
nothing owns price per store view because the platform cannot store
one" is.

The vocabulary for this predates e-commerce. Pat Helland's
[Data on the Outside versus Data on the Inside](https://www.cidrdb.org/cidr2005/papers/P12.pdf)
(CIDR 2005) states the rule in one sentence: "Reference data refers
to a type of information that is created and/or managed by a single
service and published to other services for their use ... For each
piece, there is exactly one publishing service."

The data-management literature says the same thing with different
words, and it is worth borrowing them because they name the two roles
a store's systems play. The DAMA-DMBOK, second edition, chapter 10
(Reference and Master Data), defines a System of Record as "an
authoritative system where
data is created/captured, and/or maintained through a defined set of
rules and expectations," and a System of Reference as "an
authoritative system where data consumers can obtain reliable data to
support transactions and analysis, even if the information did not
originate in the system of reference." One of its six guiding principles for
reference and master data is Authority: "Master Data values should be
replicated only from the system of record." Another is Ownership,
which it frames at the level of the organization rather than the
field. Your storefront is a system of reference for most of the
product record, and the argument this post is about is which system
is the record for each field.

What the literature stops short of is the granularity. The second
edition names the designation, and names match, merge, survivorship
and trust rules among the business rules master-data management
needs, but it addresses entities and data elements in general rather
than the specific question of which system owns a storefront's alt
text in Polish. The
four MDM styles usually cited as registry, consolidation, coexistence
and transaction are widely attributed to Gartner; Gartner's own pages
refused every client we tried, and the openly readable source we
found attributes the styles to
[data-management consultants and MDM vendors](https://www.techtarget.com/searchdatamanagement/definition/master-data-management)
rather than to Gartner, so we use them as a common description and
not as a definition.

Propagation has better-named patterns. A push feed is an
event-driven consumer and a nightly job is a
[polling consumer](https://www.enterpriseintegrationpatterns.com/patterns/messaging/PollingConsumer.html);
tolerating a repeated message is
[Idempotent Receiver](https://www.enterpriseintegrationpatterns.com/patterns/messaging/IdempotentReceiver.html),
whose two documented routes are explicit de-duplication and
semantics that make reprocessing harmless; and restoring order in a
stream that arrived out of order is a
[Resequencer](https://www.enterpriseintegrationpatterns.com/patterns/messaging/Resequencer.html).
Helland's
[Life beyond Distributed Transactions](https://www.cidrdb.org/cidr2007/papers/cidr07p15.pdf)
(CIDR 2007) states the requirement these patterns exist to meet:
"the application must tolerate message retries and the out-of-order
arrival of some messages."

## What your platform can express

An ownership rule the platform cannot express cannot be implemented,
so check the rule against the data model before agreeing it with
anyone.

**Magento scopes by store hierarchy.** Adobe documents a
[cascade of global, website, store and store view](https://experienceleague.adobe.com/en/docs/commerce-admin/start/setup/websites-stores-views),
but a product attribute is scoped at only three of those four: the
store level carries the root category rather than attribute values,
so an attribute is global, per website or per store view. Two limits
decide most ownership questions. Price is not freely scopable: the
[Catalog Price Scope](https://experienceleague.adobe.com/en/docs/commerce-admin/catalog/products/pricing/catalog-price-scope)
setting offers Global or Website only, the page states plainly that
"Commerce does not allow setting a product price for each store,"
and the admin exposes the setting at Default Config scope only, so
it is one switch for the whole installation. Some attributes cannot
be rescoped at all: Magento locks the scope selector on `sku` and
`category_ids` in
[eav_attributes.xml](https://raw.githubusercontent.com/magento/magento2/2.4-develop/app/code/Magento/Catalog/etc/eav_attributes.xml)
and disables it for `sku` and `media_gallery` in
[the admin form's configuration](https://raw.githubusercontent.com/magento/magento2/2.4-develop/app/code/Magento/Catalog/etc/adminhtml/di.xml)
(2.4-develop, checked August 4, 2026). An attribute used as a
configurable option
[has to be Global](https://experienceleague.adobe.com/en/docs/commerce-admin/catalog/product-attributes/product-attributes-add),
though its option labels stay translatable per store view.

**Shopify separates pricing from translation, and they are different
mechanisms.** A variant carries one base price on the product
record; an authored per-market price lives outside the product
entirely, on a price list attached to a catalog attached to a market.
A market can also diverge from the base price without any price list,
through currency conversion and rounding rules. Magento has no
equivalent: an authored price per market means a website per market,
with the store views beneath it sharing that price. Translation is a
separate surface, and on the product resource itself it is narrow:
only title, body, handle, product type, meta title and meta
description are translatable, and
[a resource's tags cannot be translated](https://shopify.dev/docs/apps/build/markets/manage-translated-content)
at all. Option names, option values and publicly accessible
metafields are translatable too, as their own resource types. A
translation can also be scoped to one market through the `marketId`
on the translation input, so the same language can read differently
in two markets. URL handles are the exception: Shopify states they
cannot be customized per market. Two mechanics matter for whoever
owns the write path.
writing a translation requires the source's
`translatableContentDigest`, and
[`Translation.outdated`](https://shopify.dev/docs/api/admin-graphql/latest/objects/Translation)
reports whether the original content has changed since the
translation was written. That makes staleness detectable; it does not
resolve it. And `productSet`
reconciles list fields against the payload you send: for variants,
metafields and collections it creates and updates what is in the
payload and deletes what is not, which makes a naive partial "sync
everything" job destructive. Behaviour above is the 2026-07 Admin API,
checked August 4, 2026.

## The field-by-field answer

| Field | System of record | Scope it can actually hold | On conflict |
| ----- | ---------------- | -------------------------- | ----------- |
| Product identity | ERP, as a surrogate id | Keep the ERP id in a Magento attribute or a Shopify metafield; do not join on SKU, which gets renamed | ERP id wins; a changed SKU is a rename, not a new product |
| List price | ERP | Magento: global or per website only. Shopify: one base value per variant | ERP wins; store edits are overwritten on next sync |
| Tax basis and tax class | ERP | Magento: `tax_class_id` is a website-scoped attribute, and net-or-gross display is separate configuration. Shopify: a product flag plus per-market tax settings | Decide which side of the VAT multiplication is authoritative and write it down. A Czech or Polish B2C catalogue is authored gross, so deriving gross from a net ERP price puts rounding between the ERP and the price the customer sees |
| Market or channel price | Store | Shopify price lists per catalog per market, plus currency conversion. Magento cannot separate the two: the website price is the only value, so whoever owns list price owns market price | Store wins for display. The ERP still receives the sold price on the order, and must not re-price an imported order from its own list |
| Promotional price | Store, unless the ERP holds margin approval | Magento: same envelope as list price, or a catalog price rule per website and customer group. Shopify: compare-at price, or a catalog adjustment | If margin approval sits in the ERP, the ERP owns it and the store must not also run catalog rules on the same products |
| B2B or contract price | ERP | Magento: customer-group tier prices per website; shared catalogs only with Adobe Commerce B2B. Shopify: catalogs per company location | ERP wins. Above a few dozen price profiles neither platform models per-customer contracts well |
| Physical stock | ERP, or the WMS where one exists | Per source. Salable quantity is computed by the platform from sources minus reservations and is not writable | Never write salable quantity; write source quantity and let the platform derive |
| Variant set | PIM, else store | Magento configurable products need global option attributes; most ERPs hold each variant as its own item with no parent | Whoever owns the parent grouping owns it; the ERP usually cannot express one |
| Attributes and options | PIM, else store | Configurable-option attributes have to be global on Magento | PIM wins; the store is a display copy |
| Media files | DAM, else PIM | One global file set; on Magento the base, small and thumbnail roles are per store view | DAM wins, but only if it keeps a stable identity per asset; renaming on re-sync orphans every per-store-view role |
| Alt text | PIM, else store | Per store view on Magento, per locale on Shopify | Copy owner wins |
| Per-locale copy | ERP up to its language ceiling, else PIM, else store | Magento store views; on Shopify five of the six translatable product fields, plus option names, option values and publicly readable metafields (the handle is the URL row) | Source locale wins; a stale translation is flagged, not replaced |
| URL key or handle | Store | Per store view on Magento; per locale on Shopify, but handles cannot be customized per market | Store wins; never regenerate from the product name |
| Publication and delisting | ERP for eligibility, store for channel | The ERP flag (`isInternet`, `exportNaEshop`) gates the catalogue; the store publishes per website or channel | Disable rather than delete: a deleted product loses its URL, its reviews and its rewrite history |
| Category or collection membership | PIM, else store | One global assignment on Magento; collections on Shopify. An ERP product-group tree is an input, not the record | PIM wins; the ERP tree is mapped, not mirrored |
| Regulatory fields | Store, filled from supplier records | Per market, in a language that market's Member State accepts | Nobody may overwrite an attestation automatically |

Two rows need spelling out: media and URL keys.

**An image is global; its alt text is not.** Adobe states that "New
product images are **_always_** uploaded and visible in **_all_**
store views, even if the `All Store Views` scope is not used for
upload"
([product images and video](https://experienceleague.adobe.com/en/docs/commerce-admin/catalog/products/digital-assets/product-image),
checked August 4, 2026), and the gallery stores one file per image
with no store column. A DAM therefore owns the asset set for every
locale at once. What is per store view is the row beside each image:
label, position and a disabled flag, which makes alt text, image order
and which image is hidden all per-store-view fields. One caveat that
complicates the tidy split: the image *roles* (base, small,
thumbnail, swatch) are store-view-scoped attributes holding a file
path, so which of the global files a storefront renders can itself
differ per locale. Shopify draws the line in the same place from the
other direction: on a media image the only translatable field is
`alt`. Its
[Translate & Adapt documentation](https://help.shopify.com/en/manual/international/translate-adapt-app)
lists product images among the content types the app cannot translate,
while other images and videos on a translated resource can be swapped
per language by uploading an alternate file (checked August 4, 2026).

That split matters more than it looks, because alt text is not a
technical field. The
[European Accessibility Act](https://eur-lex.europa.eu/eli/dir/2019/882/oj)
covers e-commerce services sold to consumers, and Member States have
had to apply its measures since 28 June 2025. The Directive itself
requires those services to be perceivable, operable, understandable
and robust rather than naming alt text; the concrete
text-alternative requirement is expressed by EN 301 549, which points
at WCAG. Note that the version in force, V3.2.1, was harmonised under
the Web Accessibility Directive rather than under the Accessibility
Act, and the EAA-facing V4.1.0 was still not cited in the Official
Journal when we checked. Its microenterprise exemption is
[narrower than it looks](/blog/accessibility-act-ecommerce/), and a
separate disproportionate-burden assessment is open to any provider. Alt
text is per-language content with a
compliance regime attached, authored wherever the rest of the copy is
authored. Nothing in either platform's upload path prompts for it
per locale.

**The URL key usually belongs to the store, but not because nothing
else claims it.** Most ERPs have no opinion about storefront URLs,
and the temptation is to conclude the field has no competing
claimant. It does. Comarch ERP Optima's own e-Sklep documentation
gives the ERP a Pozycjonowanie (positioning) tab holding the page
title, a dedicated `Link` field for building URLs, keywords and a
meta description, for product groups and individual items alike
([Comarch Optima help, version 2026_5](https://pomoc.comarch.pl/optima/pl/2026_5/dokumentacja/wspolpraca-z-comarch-e-sklep/),
checked August 4, 2026). Connectors and PIMs write handles too,
whatever the ERP core documents.

The operational rule is better than the scope argument, because
Comarch shows an ERP can express the field. Whoever owns the URL key
owns every consequence of changing it, and those consequences land
outside the system that made the change. The decision that matters is
therefore what happens on rename. Magento makes that a setting,
"Create Permanent Redirect for URLs if URL Key Changed," and whoever
owns the key inherits a growing rewrite table.

Letting an external system churn that field has a direct cost.
Heureka's
[feed specification](https://sluzby.heureka.cz/napoveda/xml-feed/)
marks four elements unconditionally mandatory, product name, item ID,
price with VAT and URL, and states, in Czech, that when product URLs,
names or categories change in the XML all products are unpaired from
their Heureka product cards and then wait to be paired again, which
it says can take about four working days. A PIM that regenerates handles
from product names will
therefore unpair the whole catalogue from the comparison engine for
several days, without anything in the store appearing broken.

## Where the ERP stops: per-locale copy

For a store selling in Czech, Slovak, German and Polish, the
dividing line between "the ERP can own product copy" and "something
else must" is usually the number of languages the ERP's data model
admits, and it is lower than the number of markets a store of this
size sells into.

ABRA Flexi owns multilingual copy in its core price-list entity, but
as a fixed number of columns rather than a list: one primary name and
description plus three more, visible in
[the entity's own published field schema](https://demo.flexibee.eu/c/demo/cenik/properties.json)
(checked August 4, 2026, where the demo company labels them English,
German and French). That is four language slots in the
core entity, and ABRA's own support article confirms more languages
are possible only by adding per-language custom fields, which is
integration work rather than configuration. Money exposes localized
names and
descriptions through the
[PLUS views of its e-commerce connector](https://developer.moneyerp.com/eshop-konektor/vycitani-dat-e-shopem/),
and Comarch ERP Optima carries per-language names and descriptions on
the same e-Handel tab as its SEO fields. Business Central exports item
translations to Shopify one way, and was the only system in this group
whose documentation described a custom-field bridge, mapping its
fields to Shopify metafields. For SAP Business One and InsERT we found
no documented multi-locale product-copy export, though SAP's
documentation portal renders only to a JavaScript client and we could
not read all of it, so treat that as unconfirmed rather than absent.

Two more ERP-side limits break integrations quietly, because both
are hard ceilings rather than errors. ABRA Flexi encodes quantity
tiers as fixed columns rather than rows, capping volume pricing at
five tiers. Helios expresses each price level in at most six
currencies, one domestic and five foreign. A tier grid or currency
list that outgrows the ERP's
shape stops being expressible in the system of record, without
raising an error.

Worth finding before anything else: the flag that decides which SKUs
the storefront may see. Every system has one and each names it
differently, `isInternet` on a
[POHODA stock card](https://www.stormware.cz/schema/version_2/stock.xsd),
`exportNaEshop` on an ABRA Flexi price-list item, documented in its
[published field schema](https://demo.flexibee.eu/c/demo/cenik/properties.json)
and used as the filter in ABRA's own integration guide.
Whoever owns that flag controls the catalogue, whatever the rest of
the design says. Helios settles the direction of authority in its API
surface instead: of the seventeen paths in its
[published eShop API description](https://public.helios.eu/inuvio/api/eshop/Inuvio_doc_api_eshopv2.json),
only orders and customers accept writes. Products, categories, price
lists and inventories are read-only, which makes the ERP
authoritative by construction.

## The fields the law added

Some of the contested fields are new, and they arrived from
regulation rather than from merchandising, which is why no system
was designed to own them.

The
[General Product Safety Regulation](https://eur-lex.europa.eu/eli/reg/2023/988/oj)
(Regulation (EU) 2023/988, applicable since 13 December 2024)
requires that a distance-sales offer carry the manufacturer's name
and both postal and electronic address, the same for a non-EU
manufacturer's responsible person, information identifying the
product including a picture and its type, and any warning or safety
information "in a language which can be easily understood by
consumers, as determined by the Member State in which the product is
made available on the market." That last clause makes safety text a
per-market content field, and the language is the destination
Member State's call rather than yours. The regulation also requires
an EU-established economic operator responsible for each product.

Energy labelling adds more.
[Regulation (EU) 2017/1369](https://eur-lex.europa.eu/eli/reg/2017/1369/oj)
names online distance selling explicitly in the dealer's duty to
display the label (Article 5(1)(a)); the product information sheet has
to be made available to customers under the following point, without
that qualifier. Article 6(a) separately requires a visual
advertisement for a specific model to carry both the efficiency class
and the range of classes available on the label. Its EPREL database has
required suppliers to register each new model since 1 January 2019.
The consequence reaches the feed:
[Google Merchant Center](https://support.google.com/merchants/answer/7052112)
has required an EPREL registration code in the certification
attribute for affected EU-targeted products since April 2025, and
now limits its energy efficiency class attribute to Switzerland,
Norway and the United Kingdom.

The channels have already modelled these fields.
[Allegro's API](https://developer.allegro.pl/documentation) carries
responsible persons and responsible producers as their own
resources, per-offer safety information and a flag for products
marketed before the GPSR obligation. Heureka documents dedicated
manufacturer postal and electronic address tags. So these fields
need a system of record that can attest to them per market and per
language, and often no existing system holds one: an ERP records a
supplier rather than a responsible person, and a storefront records
copy rather than an attestation. The practical placement is a
metafield or attribute set per market on the storefront, filled at
supplier onboarding rather than at listing time, with the empty-field
check applied to
new and edited products rather than retroactively. Run it as a gate on
new listings and as a report on the existing catalogue: applied to a
catalogue of thousands of SKUs from dozens of suppliers, a hard block
unpublishes the store on the day it is switched on.

## B2B pricing is a different mechanism on each platform

Adobe puts B2B pricing in shared catalogs, which are part of the
Adobe Commerce B2B module and therefore unavailable on Magento Open
Source or Mage-OS. Enabling them adds a Shared Catalog option to
the Customer Group selector on the product's
[Advanced Pricing](https://experienceleague.adobe.com/en/docs/commerce-admin/catalog/products/pricing/pricing-advanced)
page, so the same tier grid is edited from either side.

Shopify routes B2B through the same catalog and price-list machinery
as markets, with the catalog scoped to a company location. The plan
limits are the constraint. Shopify's
[B2B catalog documentation](https://help.shopify.com/en/manual/b2b/catalogs)
states that on the Basic, Grow and Advanced plans "you can assign up
to 3 active catalogs across all your B2B markets," while Plus offers
an unlimited number and direct assignment to companies and locations
(checked August 4, 2026). Where several catalogs apply to one company
location, the lowest price is the one displayed. Microsoft's
[Business Central connector documentation](https://learn.microsoft.com/en-us/dynamics365/business-central/shopify/synchronize-items)
states that its B2B price synchronization requires a Shopify Plus
subscription, and that catalog membership is managed in Shopify's
admin rather than in the ERP.

The ownership rule that follows is the same on both: the ERP owns
what a given customer has been contracted to pay, and the platform
owns which catalog that customer is attached to. Splitting it any
further puts contract terms in a merchandising tool.

## When a PIM earns its keep

A PIM is worth its cost at the point where per-locale, per-channel
values stop fitting in the platform. Both leading options model that
directly, and their licensing differs enough to decide the choice
before the features do.

Akeneo's mechanism is two independent flags on each attribute,
localizable and scopable. A product value is a triple of locale,
scope and data, and a channel bundles the locales, currencies,
category tree and conversion units for one publication target. Its
Community Edition is open source under OSL-3.0 and actively
maintained, with release v2026.3 tagged on 30 March 2026, and Akeneo
scopes its end-of-support table to the paid editions rather than to
Community. The caveat is upgrades: Community switched to
calendar versioning and Akeneo disclaims backwards compatibility
between any two releases. Commercially it sells three SaaS tiers, and
its comparison page
renders pricing through client-side scripting rather than as static
text, so we do not quote a figure from it. Third-party price figures
circulate for Akeneo; none is corroborated on an Akeneo page and we
do not repeat them.

Pimcore, based in Salzburg, changed licence in a way that matters
directly to this article's reader.
[Since Platform Version 2025.1 it is no longer open source](https://pimcore.com/en/resources/blog/breaking-free-pimcore-says-goodbye-to-gpl-and-enters-a-new-era-with-pocl):
the publicly available code is under the Pimcore Open Core Licence,
a source-available licence, and its own `composer.json` on the
current branch declares the licence as proprietary. The
[licence text](https://raw.githubusercontent.com/pimcore/pimcore/2026.x/LICENSE.md)
grants free production use only to organizations whose total global
revenue does not exceed EUR 5 million annually, self-certified and
subject to audit with retroactive fees, forbids offering Pimcore as
a hosted or managed service, forbids running GPLv3-licensed Pimcore
alongside it, and includes a telemetry clause the licensee agrees
not to interfere with. Its
[published list prices](https://pimcore.com/en/pricing) are $9,900 a
year for Professional and $29,900 for Enterprise, both on-premises,
with PaaS quoted. For a store above EUR 5 million in revenue,
Pimcore is a commercial licence purchase.

## The procedure

Write the field list before choosing any tool. For each field, name
the system that creates and maintains the value, the scope at which
the platform can store it, and what happens when the two sides
disagree. Direction follows from the first of those: the system of
record writes and everything else reads, which is why a field with
two writers has no owner. Then check three things that catch most
designs: that the scope you assumed exists (price per store view
does not on Magento), that the owner's data model can hold the range
you need (five currencies, five tiers, three extra locales), and
that nothing else writes the same field behind your back. Bidirectional
editing of one field in two systems is the design to avoid, and it
is usually reached by omission rather than by choice.

Then decide the propagation, remembering that the first load and the
steady state are different systems. The initial catalogue load is a
bulk job: Shopify's bulk operations take JSONL and run asynchronously,
and Magento has async bulk REST and the CSV importer. The steady state
is a delta, and the mechanism is dictated by what the owner can emit.
An ERP that offers only a nightly file export cannot push, however the
design is drawn, so the delta becomes a scheduled pull with a
changed-since filter, and the storefront's freshness is bounded by the
export interval whatever anyone promised. Reconciliation is the third
job, not an optional one: a periodic full comparison that finds what
the delta missed, because a feed nobody audits drifts silently.

On Shopify one more rule follows from how
[`productSet` synchronizes](https://shopify.dev/docs/apps/build/graphql/migrate/new-product-model/sync-data):
within a list field you send, it deletes the entries you leave out, so
a partial variant list removes the variants it omits. Use it only
where the sending system owns the whole of every list it sends, and
use the targeted mutations where ownership is split.

Mapping that field list, and building the integrations that carry
it, is what our
[integrations service](/services/integrations/) covers, and the
custom work above the platform's data model is
[custom development](/services/custom-development/). Whichever tools
you choose, the field list is what the integration is built from.