Summary
This document describes how Pimcore product data is transferred into iPaaS.com. Products, along with their variants, category assignments, and related products, are sent from Pimcore to iPaaS.com through the Pimcore Datahub GraphQL API and webhooks. It covers the field-naming conventions, subscription settings, conversion functions, per-collection mappings, and the caveats that apply when configuring a transfer.
The mapping collections shipped with a new Pimcore subscription are an example configuration built on the Pimcore Cars demo data. They demonstrate every feature described here, but a real implementation uses entirely different Pimcore classes, fields, and formulas. Treat the specific source paths, formulas, and static values throughout this document as illustrative of the technique rather than values to be used as-is.
Related documents: For one-time setup, see the Pimcore Installation Instructions (Pimcore Datahub, webhook, and subscription setup) and Pimcore Connections and Settings (the full list of subscription settings). This document focuses on how data is mapped once that setup is complete.
How the Integration Works
Pimcore is the source system; data flows in one direction, from Pimcore to iPaaS.com. The integration does not create, update, or delete records in Pimcore.
A product changes in Pimcore and a Datahub webhook notifies iPaaS.com, or a subscriber initiates a Manual Sync or a scheduled poll.
The integration retrieves the full product record and its child data (variants, category assignments, and related products) from the Pimcore Datahub GraphQL API.
The mapping collections transform that data into an iPaaS.com Product and its child records, resolving Pimcore references to existing iPaaS.com records where required.
The product is created or updated in iPaaS.com, linked by its external id so that later transfers update the same record.
Field Naming Convention
Every value you transfer must be configured in iPaaS.com as a subscription custom field, and every child class you use must be declared in the subscription settings. In both places the same naming convention is used — the full Datahub GraphQL path to the value:
Dot notation indicates child fields or entities. The
descriptionfield on theCarentity is named Car.description.Names begin with the entity, without the
getprefix. ThegetCarquery produces names starting with Car, not getCar.Type conditions are included in brackets as a separate dot. The manufacturer name reached through a
Manufacturertype condition is Car.manufacturer.[on object_Manufacturer].name.Field arguments are written in parentheses immediately after the field name, mirroring GraphQL syntax. A description requested in French is Car.description(language: "fr").
Image galleries are named by appending !hotspotimage to the gallery path (for example Car.genericImages!hotspotimage). With this flag the integration returns the gallery as a list of image objects compatible with the image conversion functions; individual sub-fields do not need to be declared, and no data type needs to be set on the custom field.
Building a sample query in a GraphQL tool such as Postman (using introspection against your Datahub configuration) is the most reliable way to discover the exact entity names, field names, type conditions, and arguments for your data.
Classname
Define the classname custom field wherever the entity exposes it — it is required for the integration to build the external ids that link records together. An iPaaS.com external id needs both a type and an id (for example Car:123), and the integration uses the classname value as the type prefix. Without classname, the integration falls back to a prefix generated from the data context: the record still receives a unique id, but that id will not match when another record looks it up by its <ClassName>:<id> external id — which silently breaks category assignments, related-product links, and parent/child references. This applies to child references too: if you carry a parent id such as Category.parent.[on object_Category].id, you must also define Category.parent.[on object_Category].classname so the reference resolves.
Collections and Complex Values
To read data stored in an array or complex object, define a custom field for each child value you need, and also for the object or array itself if you want it as a whole. When a custom field value is a complex object the integration returns its JSON representation; when it is a single field inside an array of objects it returns a comma-separated list of those values; when it is a single value inside a complex object it returns that value directly.
External ID Format
After a successful transfer, iPaaS.com records the product against an external id in the form <ClassName>:<id> — for example Car:261. The class-name prefix comes from the record's Pimcore class (via the classname custom field described above). This external id is what links a later transfer of the same product to the existing iPaaS.com record, so the record is updated rather than duplicated. Child records (variants, related products, category assignments) are linked by the same prefixed-id convention.
When performing a Manual Sync for a single record, enter the Pimcore record id on the iPaaS.com Manual Sync page. For a bulk transfer, enter a Pimcore polling filter as the Manual Sync value (see Polling below).
Conversion Functions
The functions below are available for use in mapping formulas. They are the building blocks of the example mappings and are the primary way to access and transform Pimcore data. Each entry lists its parameters and an example drawn from the Cars demo data.
Several values are supplied automatically by the integration and can be referenced directly in a formula: CustomFields (the record being transferred), Parent.CustomFields (the parent product, available only in a child/variant collection), RetrievedVariants (populated from the Variant Class Names setting), RetrievedCategoryAssignments (from the Product Category Assignment Class Names / Variant Category Assignment Class Names setting), RetrievedRelatedProducts, ClassName, Id, OriginalJToken, and SpaceportSystemId.
PimcoreCustomFieldValue
Returns the value of a named custom field from a set of custom field objects, or nothing if the field is not present. This is the most common accessor for reading a Pimcore value in a formula.
inputObject: the custom-field collection to read from — usually CustomFields, or Parent.CustomFields to read a parent value from within a variant collection.
customFieldName: the full Datahub path of the value to read.
Example: PimcoreCustomFieldValue(CustomFields, "Car.manufacturer.[on object_Manufacturer].name")
ConvertCategoriesToSpaceportIds
An asynchronous function that converts a list of Pimcore category assignments into their matching iPaaS.com category ids, omitting any that are not yet linked. Its result maps directly to the Categories field of a Product or Product Variant.
categories: the list of category assignments to resolve — usually RetrievedCategoryAssignments, which the integration populates from the category-assignment class-name setting.
Example: await ConvertCategoriesToSpaceportIds(RetrievedCategoryAssignments)
GetSpaceportIdAsync
An asynchronous function that resolves a prefixed external id (such as Car:261) to the matching iPaaS.com record id for a given data type, or nothing if no such record exists. Used to link related products and parent categories to records that already exist in iPaaS.com.
externalId: the
<ClassName>:<Id>external id to look up.dataType: the iPaaS.com data type to search — for example Product, Product Variant, or Product Category.
systemId: the subscription to search, normally SpaceportSystemId (supplied by the integration).
Example: GetSpaceportIdAsync(ClassName + ":" + Id, "Product", SpaceportSystemId)
ParseVariantsFromFieldsToiPaaS
Builds a product's options and values from a comma-separated list of variant field paths. The result maps to the product Options field. Use this when each variant dimension is stored in its own field.
variants: the variant list, usually RetrievedVariants.
fieldNames: a comma-separated list of the variant field paths that hold the option values.
className, id: the parent record's ClassName and Id (supplied by the integration).
Example: ParseVariantsFromFieldsToiPaaS(RetrievedVariants, "Car.children.[on object_Car].color,Car.children.[on object_Car].size", ClassName, Id)
ParseVariantsFromCollectionToiPaaS
Builds a product's options and values from a collection of attribute objects (for example, a Pimcore classification store). The result maps to the product Options field. An entry whose value field is empty is not created as an option.
variants: the variant list, usually RetrievedVariants.
collectionPath: the path, relative to the variant, of the attribute collection.
optionNameField: the field within each entry that holds the option name.
optionValueField: the field within each entry that holds the option value.
className, id: the parent record's ClassName and Id.
Example: ParseVariantsFromCollectionToiPaaS(RetrievedVariants, "VariantConfiguration.features", "name", "selection", ClassName, Id)
ParseVariantOptionValuesFromFieldsToiPaaS
The variant-side counterpart of ParseVariantsFromFieldsToiPaaS. It maps a single variant's selected option values from a field or fields, and is mapped to the Options field of the Product Variant.
customFields: the variant's custom fields, usually CustomFields.
fieldNames: a comma-separated list of the variant field paths that hold the option values.
variantId: the variant's Id.
Example: ParseVariantOptionValuesFromFieldsToiPaaS(CustomFields, "Car.children.[on object_Car].color,Car.children.[on object_Car].size", Id)
ParseVariantOptionValuesFromCollectionToiPaaS
The variant-side counterpart of ParseVariantsFromCollectionToiPaaS, mapped to the Options field of the Product Variant. The originalJToken parameter must be passed unchanged.
collectionPath: the path, relative to the variant, of the attribute collection.
optionNameField: the field within each entry that holds the option name.
optionValueField: the field within each entry that holds the option value.
originalJToken: pass the OriginalJToken reference exactly, without modifying it.
Example: ParseVariantOptionValuesFromCollectionToiPaaS("VariantConfiguration.features", "name", "selection", OriginalJToken)
GetImageURLsFromProductGallery
Returns a comma-separated list of image URLs from a Pimcore image gallery. The input must come from a gallery custom field whose path ends in !hotspotimage.
gallery: the gallery object, read with PimcoreCustomFieldValue from a !hotspotimage custom field.
Example: GetImageURLsFromProductGallery(PimcoreCustomFieldValue(CustomFields, "Car.genericImages!hotspotimage"))
GetImageIdsFromProductGallery
Returns a comma-separated list of image ids from a Pimcore image gallery. Same input requirement as GetImageURLsFromProductGallery.
gallery: the gallery object, read with PimcoreCustomFieldValue from a !hotspotimage custom field.
Example: GetImageIdsFromProductGallery(PimcoreCustomFieldValue(CustomFields, "Car.children.[on object_Car].gallery!hotspotimage"))
GetPresetValue
Returns the value of a subscription preset (setting) by name. Use it when a formula needs a configured setting value.
presetName: the exact name of the subscription setting to read.
Example: GetPresetValue("Datahub Config")
ParseJsonArrayToDictionary
Converts a JSON array of objects into a set of key/value pairs, using the named fields as the key and value. Useful when a Pimcore value is returned as a JSON array you need to look values up in.
json: the JSON array string.
keyFieldName: the field in each object to use as the key.
valueFieldName: the field in each object to use as the value.
Example: ParseJsonArrayToDictionary(PimcoreCustomFieldValue(CustomFields, "Car.tags"), "id", "name")
ConvertDateTimeToUnixTimestamp and ConvertUnixTimestampToDateTime
Convert between a date/time and a Unix (Epoch) timestamp. Pimcore Datahub filters expect dates in Epoch seconds, so these help when building polling filters or comparing dates in a formula.
ConvertDateTimeToUnixTimestamp(dateTime): takes a date/time and returns the Epoch seconds.
ConvertUnixTimestampToDateTime(unixTimestamp): takes Epoch seconds and returns the date/time.
Example: ConvertDateTimeToUnixTimestamp(CurrentDateTimeOffset())
Mapping Collection Status and Trigger Events
Status: the example product, variant, related-product, and category collections are Enabled. The four Custom Field Template Placeholder collections are Disabled by design (their filter blocks all records) — they exist only to carry custom field definitions into the template mappings. The Pimcore Required Webhook Message collection is Enabled and must not be deleted.
Trigger Events: automatic transfers occur when a Pimcore Datahub webhook is configured for the relevant class, using the
pimcore.dataobject.postAddandpimcore.dataobject.postUpdateevents. The webhook is configured on the Pimcore side (see the Installation instructions); there is no separate webhook subscription to enable on the iPaaS.com side. Manual Sync is available on every collection regardless of webhook configuration.Webhook prerequisite: every automatic (webhook) transfer also depends on the required Pimcore Webhook Message collection, which receives all incoming Pimcore webhooks before they are routed to a data collection. See the Pimcore to iPaaS.com Webhook Message Mapping Documentation; do not delete that collection or webhook-driven transfers stop working.
Mappings
Each mapping collection below lists its filter (where one applies) and its field mappings. Source paths, formulas, and static values are from the Cars demo configuration.
Add/Update Pimcore Product (Example) TO iPaaS.com
Mapping Filter
PimcoreCustomFieldValue(CustomFields, "Car.objectType") == "virtual-car" && FirstMatch(RetrievedVariants, "PimcoreCustomFieldValue(CustomFields, \"Car.children.[on object_Car].objectType\") == \"actual-car\"") != null
Filter Description. Only records that represent a parent product with at least one variant are processed: the record's Car.objectType must be virtual-car (the parent product) and at least one of its variants must have an objectType of actual-car. Records that do not meet both conditions are skipped. The virtual-car and actual-car values are specific to the Cars demo data; a real implementation replaces this filter with the condition that identifies parent products in its own data.
Mapping Type | Source Field (Pimcore) | Destination Field (iPaaS.com) | Description |
Dynamic Formula |
| Sku | Required. Unique product SKU. Composed from several Car values because the demo data has no dedicated SKU field; most implementations map a dedicated field directly. |
Dynamic Formula |
| Name | Required. Product name, composed from Car values in the demo; usually a dedicated field. |
Dynamic Formula | parent/variant price fallback | DefaultPrice | Required. Reads the parent price, falling back to the first variant price when the parent has none. Returns nothing if neither is present, which surfaces the missing-required-field error. |
Static |
| Type | Required. Allowed values: Physical, Virtual. |
Static |
| Status | Required. Allowed values: Preorder, Active, Disabled, Discontinued. |
Dynamic Formula | variant-option count | TrackingMethod | Required. Allowed values: Product, Variant. Returns Variant when variant options are found, otherwise Product. When Variant, the product is tracked at the variant level and variants transfer with it. |
Dynamic Formula |
| Options | Recommended for configurable products. Builds the product's variant options from the variant field paths. |
Dynamic Formula |
| Categories | Recommended. Resolves the product's Pimcore categories to iPaaS.com category ids; referenced categories must already exist in iPaaS.com. |
Field |
| Description | Optional. Direct field mapping; demonstrates a language argument in a custom-field path. |
Field |
| Pimcore Car Manufacturer ID | Optional custom field. Reads a related-object value through a type condition. |
Field |
| Pimcore Car Manufacturer Name | Optional custom field. |
Field |
| Pimcore Car Production Year | Optional custom field. |
Dynamic Formula |
| Pimcore Car Image URLs | Optional. Comma-separated image URLs from a !hotspotimage gallery. |
Dynamic Formula |
| Pimcore Car Generic Image URLs | Optional. As above, for a second gallery. |
Add/Update Pimcore Product Variant (Example) TO iPaaS.com
Child collection of the Product collection. Variants transfer as part of their parent product; a variant re-syncs by re-syncing its parent. This collection has no mapping filter.
Mapping Type | Source Field (Pimcore) | Destination Field (iPaaS.com) | Description |
Dynamic Formula |
| Sku | Required. Must be unique and must not match the parent product SKU. Reads parent values through Parent.CustomFields. |
Dynamic Formula |
| Options | The variant's selected option values. Required for configurable products. |
Field |
| SalePrice | Optional. The demo maps the variant price into SalePrice; map your own price fields as needed. |
Field |
| Height | Optional. The demo maps Pimcore length into Height; map your own dimension fields as needed. |
Field |
| Weight | Optional. |
Field |
| Width | Optional. |
Field |
| Pimcore Car Variant Description | Optional custom field. |
Dynamic Formula |
| Pimcore Car Variant Manufacturer Name | Optional custom field. Reads a parent value via Parent.CustomFields. |
Dynamic Formula |
| Pimcore Car Variant Image URLs / Image Ids | Optional. Image URLs and ids from a !hotspotimage gallery. |
Dynamic Formula |
| Pimcore Car Variant Generic Image URLs / Generic Image Ids | Optional. As above, for a second gallery. |
Add/Update Pimcore Product Related Product (Example) TO iPaaS.com
Child collection of the Product collection.
Mapping Filter
var siblingId = ClassName + ":" + Id; var siblingSpaceportId = await GetSpaceportIdAsync(siblingId, "Product", SpaceportSystemId); return (siblingSpaceportId != null);
Filter Description. The related record's external id is built as ClassName:Id and resolved to an existing iPaaS.com Product id. The relationship is processed only when that product already exists in iPaaS.com; if it does not resolve, the related record is skipped. Related products must therefore be transferred to iPaaS.com before their relationships.
Mapping Type | Source Field (Pimcore) | Destination Field (iPaaS.com) | Description |
Dynamic Formula |
| RelatedId | Required. The iPaaS.com id of the related product. |
Static |
| IsVariant | Required. Indicates the related record is a product, not a variant. |
Static |
| RelatedType | Required. Allowed values: Replacement, Similar Item, Related Product. Relationships are unique by related id + type. |
Add/Update Pimcore Product Variant Related Product (Example) TO iPaaS.com
Child collection of the Product Variant collection. Identical in shape to the Related Product collection above, with two differences: IsVariant is true, and the related id resolves to an existing iPaaS.com Product Variant.
Mapping Filter
var siblingId = ClassName + ":" + Id; var siblingSpaceportId = await GetSpaceportIdAsync(siblingId, "Product Variant", SpaceportSystemId); return (siblingSpaceportId != null);
Filter Description. The related record's external id is built as ClassName:Id and resolved to an existing iPaaS.com Product Variant id. The relationship is processed only when that variant already exists in iPaaS.com; otherwise it is skipped.
Mapping Type | Source Field (Pimcore) | Destination Field (iPaaS.com) | Description |
Dynamic Formula |
| RelatedId | Required. The iPaaS.com id of the related variant. |
Static |
| IsVariant | Required. Indicates the related record is a variant. |
Static |
| RelatedType | Required. Allowed values: Replacement, Similar Item, Related Product. |
Product categories are transferred by their own mapping collection, documented separately — see Pimcore to iPaaS.com Product Category Mapping Documentation. The categories a product is assigned to must be transferred first so the product's Categories mapping can resolve them.
Webhook (automatic) transfers also depend on the Pimcore Required Webhook Message collection, which receives every incoming Pimcore webhook before it is routed to the collection above. It is a required system collection documented separately — see Pimcore to iPaaS.com Webhook Message Mapping Documentation. Do not delete it.
Variants
Only variants that are direct children of their parent product are supported. When iPaaS.com receives a webhook for a variant, the integration redirects it to the parent product, identified by the Variant Parent Field subscription setting.
There are two supported ways to define variant dimensions; the one you use depends on how the attributes are stored in Pimcore:
By fields — each dimension is a field (or multi-select field) on the variant. Use ParseVariantsFromFieldsToiPaaS on the Product's Options field and ParseVariantOptionValuesFromFieldsToiPaaS on the Product Variant's Options field, supplying a comma-separated list of the variant field paths.
By collection — the dimensions are stored in a collection of attribute objects (for example, a Pimcore classification store). Use ParseVariantsFromCollectionToiPaaS on the Product's Options field and ParseVariantOptionValuesFromCollectionToiPaaS on the Product Variant's Options field, naming the field that holds the option name and the field that holds its value. An entry whose value field is empty is not created as an option.
Polling
Polling is supported for products and categories. A polling filter is passed as plain JSON (the integration performs the required character escaping) and must meet Pimcore's Datahub filter requirements — for example, using the correct field name and a date filter formatted as Epoch time. When no filter is provided on a scheduled poll, the integration automatically filters on the time of the last poll so each run pulls only recently modified data. Scheduled polling is configured through the iPaaS.com event system.
System Caveats
Pimcore Caveats
Direct-child variants only: only variants that are direct children of their parent product are supported.
Category assignments: product and variant category assignments must use a Many-To-Many Object Relation in Pimcore, to a class configured as a Product Category Class Name in the subscription.
Introspection: keep Datahub introspection enabled during setup so field names and paths can be discovered; it is not required afterward.
Asset permissions: to use the image-URL and image-id functions, grant read permission to the relevant asset paths in the Datahub Security Definition.
iPaaS.com Caveats
Referenced categories must exist first: category ids are resolved during the transfer, so the referenced categories must already have been transferred to iPaaS.com; unresolved categories are omitted.
Referenced related products must exist first: related-product relationships resolve to existing iPaaS.com records and are skipped until those records exist.
Price is required at the product level: iPaaS.com requires a product price even when the source data holds price only at the variant level; the example DefaultPrice formula handles this with a variant fallback.
Deleted Record Support
This integration transfers data from Pimcore to iPaaS.com only. Outbound delete is not supported — deletions in Pimcore are not propagated, and delete mappings are not included in the templates.
Known Limitations
At the time this documentation was written, only direct-child variants are supported; deeper variant hierarchies are not transferred.
At the time this documentation was written, product and variant category assignments are supported only through Many-To-Many Object Relations in Pimcore.
At the time this documentation was written, the integration is one-directional (Pimcore to iPaaS.com); it does not write back to Pimcore.
Testing & Validation
Test Scenarios
Configure the Datahub webhook and confirm that adding or updating a product in Pimcore transfers it to iPaaS.com.
Update a field on an existing product and confirm the change propagates on the next transfer.
Attempt a transfer for a product missing a required field (for example, no price) and confirm the appropriate missing-required-field error.
Perform a Manual Sync using a Pimcore record id and confirm the product is created or updated.
Transfer a product with variants and confirm the parent, its variants, and their options all appear correctly.
Transfer a product with category assignments whose categories already exist in iPaaS.com, and confirm the categories are linked.
Transfer a product with related products that already exist in iPaaS.com, and confirm the relationships are created.
Validation Checklist
Required fields (Sku, Name, DefaultPrice, Type, Status, TrackingMethod) are mapped for products.
The product filter matches your parent products, not the demo
virtual-carvalue.Variant SKUs are unique and do not match their parent product SKU.
Referenced categories and related products have been transferred to iPaaS.com before the products that reference them.
Custom fields are defined for every Pimcore value used in the mappings, using the full GraphQL path names.
Related Documents
Pimcore to iPaaS.com Product Category Mapping Documentation — how Pimcore categories are transferred (referenced by the product Categories mapping).
Pimcore to iPaaS.com Webhook Message Mapping Documentation — the required webhook message collection that underpins automatic transfers.
Pimcore Installation Instructions — Pimcore Datahub, webhook, and subscription setup.
Pimcore Connections and Settings — the full list of subscription settings referenced above.










