Loading Line Sheet Data¶
In VibeIQ, "line sheet data" refers to Item, ProjectItem, and AssortmentItem data.
Item:Itemdata is global and exists outside the context of aProject.Items can also be part of a Family, as indicated by a single Family Item. Families can have Options, which are variations of the FamilyItem. In other terms, you could think of this as Product (Family) vs Colorway (Option).ProjectItem:ProjectItemdata is specific to an Item as it exists in aProject.- This is typically considered as seasonal data and can change season over season.
- If an
Itemis carried over into a following season, the data from the prior season, as represented byProjectItem, will not necessarily be the same.
- If an
AssortmentItem:AssortmentItemdata is specific to anItemas it exists within anAssortmentand aProject.- An item can exist within many different
Assortmentsin a singleProject. - Organizing your regions into many
Assortmentsis an example of this.
Despite this hierarchical structure: Item (Global) > ProjectItem (Seasonal) > AssortmentItem (Grouping/Regional), the load file for this structure remains tabular-CSV. This is possible because a single property key should not be shared across more than one of these three entities. An important note, the loader is only able to load data for one Project at a time when it comes to ProjectItems and AssortmentItems.
Loading Items¶
Required Properties¶
In your load file, you must provide the following properties for each row. These may be the CSV column headers or usage of federatedMappings or conditionalColumns in the loader configuration to match these keys.
Loading an Item Option for a Family:¶
itemFamilyFederatedId: The federatedId of the Item Option's Family Item.name: The name of the Item Option's Family Item.itemOptionFederatedIdThe federatedId of the Item Option.optionName: The name of the Item Option itself.
Upon load, the loader will search for an Item Option by itemOptionFederatedId. If one does not exist, a new Item will be created and assigned to the Item Family that has federatedId of itemFamilyFederatedId. If that Item Family does not exist, it will be created as well.
name and optionName will be updated on the Family and Option Items, respectively, if they already exist. Therefore, it's critical that name and optionName remain consistent across subsequent loads of the same Items.
loadType:
- ITEM
federatedMappings:
itemFamilyFederatedId: 'style'
itemOptionFederatedId: 'colorName'
name: 'styleName'
optionName: colorName
conditionalColumns:
- default: item:product:apparel
toProperty: typePath
- default: color
toProperty: optionGroup
{
"loadType": ["ITEM"],
"federatedMappings": {
"itemFamilyFederatedId": "style",
"itemOptionFederatedId": "colorName",
"name": "styleName",
"optionName": "colorName"
},
"conditionalColumns": [
{
"default": "item:product:apparel",
"toProperty": "typePath"
},
{
"default": "color",
"toProperty": "optionGroup"
}
]
}
Loading Only an Item Family¶
itemFamilyFederatedId: The federatedId of the Item Option's Family Item.name: The name of the Item Option's Family Item.
Upon load, the loader will search for an Item Family by itemFamilyFederatedId. If one does not exist, a new Item will be created.
name will be updated on the Family Item if it already exists. Therefore, it's critical that name remains consistent across subsequent loads of the same Items.
loadType:
- ITEM
federatedMappings:
itemFamilyFederatedId: 'style'
name: 'styleName'
conditionalColumns:
- default: item:product:apparel
toProperty: typePath
- default: color
toProperty: optionGroup
{
"loadType": ["ITEM"],
"federatedMappings": {
"itemFamilyFederatedId": "style",
"name": "styleName",
},
"conditionalColumns": [
{
"default": "item:product:apparel",
"toProperty": "typePath"
},
{
"default": "color",
"toProperty": "optionGroup"
}
]
}
Loading ProjectItems:¶
Required Properties¶
Loading ProjectItems means taking a list of Items and inserting them into a Project. An Item's existence in an Project is determined by the existence of a ProjectItem entity.
To load ProjectItems, you must specify the federatedIds for the Items you want to load into a Project. There are
two different ways you can identify this Project to load these Items into:
- Using Assortment Parameters (i.e.
assortmentSplit) if you are also loading into anAssortment. Since Assortments live withinProjects, the loader will automatically identify and select theProjectfrom the specifiedAssortment. See the "Loading AssortmentItem" section for more information. - Using the
workspaceIdentifierif you are only loadingItems into aProjectand not also loading them into anAssortment. Specify the user-definedidentifierfor theProject. You may find and manage this in the Hub UI's Project view. Click the "hamburger menu" icon to the right of the project name, select "Configure Project", and view theProject'sidentifierproperty.
Example loading just into a Project, without an Assortment load (with workspaceIdentifier):
loadType:
- ITEM
- PROJECT_ITEM
federatedMappings:
itemFamilyFederatedId: 'STYLE_NUMBER'
name: 'STYLE_NAME'
itemOptionFederatedId: 'MATERIAL_OPTION_NUMBER'
itemOption: 'MATERIAL_OPTION_NAME'
workspaceIdentifier: 'fall:2022'
{
"loadType": ["ITEM", "PROJECT_ITEM"],
"federatedMappings": {
"itemFamilyFederatedId": "STYLE_NUMBER",
"name": "STYLE_NAME",
"itemOptionFederatedId": "MATERIAL_OPTION_NUMBER",
"itemOption": "MATERIAL_OPTION_NAME"
},
"workspaceIdentifier": "fall:2022"
}
Loading AssortmentItems¶
Required Properties¶
Loading AssortmentItems means taking a list of Items and inserting them into an Assortment. An Item's existence in an Assortment is specified by the existence of an AssortmentItem entity. If you have included PROJECT_ITEM in your loadType parameter, the selected Project that will be loaded into
will be automatically selected by the loader. The Project in which the Assortment lives in will be selected.
There are two types of AssortmentItem loads:
Full Assortment Load (default)¶
When performing a full load, the entire state of the Assortment's Items will match the load file. This means that any Items not in the load file will be removed from the Assortment.
Define Assortment within Config¶
Using the parameters below, you may use the Assortment's ID or Identifier to dictate the Assortment to load into.
assortmentSplit: An object allowing you to conditionally split theItems in the load file across multipleAssortments.fieldToSplitOn: The column name in the load file to use for splitting.values: An array of objects specifying the value to split on and theAssortmentto load into.value: The value in thefieldToSplitOncolumn to split on. Example"mens".assortmentId: The ID of theAssortmentto load any rows withvaluematching in columnfieldToSplitOn.assortmentIdentifier: The identifier of theAssortmentto load any rows withvaluematching in columnfieldToSplitOn.- This may be combined with
assortmentIdonly within theassortmentSplitobject.
In the future, we will add the ability to use assortmentId and assortmentIdentifier in the top level of the configuration, but for now, these must be used within the assortmentSplit object.
Example with assortmentSplit:¶
loadType:
- ITEM
- ASSORTMENT
- PROJECT_ITEM
federatedMappings:
itemFamilyFederatedId: 'style'
itemOptionFederatedId: 'colorName'
name: 'styleName'
optionName: colorName
conditionalColumns:
- default: item:product:apparel
toProperty: typePath
- default: color
toProperty: optionGroup
assortmentSplit:
fieldToSplitOn: wearer
values:
- value: mens
assortmentId: "assortmentId1"
- value: womens
assortmentIdentifier: "assortmentIdentifier2"
{
"loadType": [
"ITEM",
"ASSORTMENT",
"PROJECT_ITEM"
],
"federatedMappings": {
"itemFamilyFederatedId": "style",
"itemOptionFederatedId": "colorName",
"name": "styleName",
"optionName": "colorName"
},
"conditionalColumns": [
{
"default": "item:product:apparel",
"toProperty": "typePath"
},
{
"default": "color",
"toProperty": "optionGroup"
}
],
"assortmentSplit": {
"fieldToSplitOn": "wearer",
"values": [
{
"value": "mens",
"assortmentId": "assortmentId1"
},
{
"value": "womens",
"assortmentIdentifier": "assortmentIdentifier2"
}
]
}
}
Partial Assortment Load¶
To add Items to an Assortment without removing existing Items that do not exist in the load file, you may do so with a few properties
within assortmentSplit. With them, you can either add or remove Items from an Assortment without requiring the entire
Assortment's state on-hand while doing the load.
assortmentSplitpartialAssortmentUpdate?: An optional boolean property indicating whether you want to perform a partial update on the Assortment instead of a full update.- Set this to
trueif you want to append theItems in the load file to the assortment(s). - Set this to
falseor omit it if you want to perform a full update on the Assortment. addField?: An optional string property where if a value exists in the column of this name, the row will be added to the Assortment. Expected values in the CSV aretrue,false, or empty''.dropField?: An optional string property where if a value exists in the column of this name, the row will be dropped from the Assortment. Expected values in the CSV aretrue,false, or empty''.fieldToSplitOn: The column name in the load file to use for splitting.values: An array of objects specifying the value to split on and the Assortment to load into.value: The value in thefieldToSplitOncolumn to split on. Example"mens".assortmentId: The ID of the Assortment to load any rows withvaluematching in columnfieldToSplitOn.assortmentIdentifier: The identifier of the Assortment to load any rows withvaluematching in columnfieldToSplitOn.- This may be combined with
assortmentIdonly within theassortmentSplitobject.
Example with partialAssortmentUpdate:¶
loadType:
- ITEM
- PROJECT_ITEM
- ASSORTMENT
assortmentSplit:
partialAssortmentUpdate: true
addField: addItem
dropField: dropItem
fieldToSplitOn: season
values:
- value: "spring"
assortmentId: "someAssortmentId"
{
"loadType": [
"ITEM",
"PROJECT_ITEM",
"ASSORTMENT"
],
"assortmentSplit": {
"partialAssortmentUpdate": true,
"addField": "addItem",
"dropField": "dropItem",
"fieldToSplitOn": "season",
"values": [
{
"value": "spring",
"assortmentId": "someAssortmentId"
}
]
}
}
Define Assortment within the Data File¶
If assortment information is not provided at the config level, you can specify the assortmentId within the data file itself. This option has some counter-intuitive restrictions, so review these limitations before using it.
- Only the first row's
assortmentIdwill be used for the entire load. The items in your load cannot go to different assortments. UseassortmentSplitif you need to load into multiple assortments. - This will perform a full load of the
Assortment. You cannot perform a partial load with this method.
To use this method, simply add an assortmentId column to your load file. The value in the first row will be used to determine the Assortment to load into.
You can simulate this behavior with conditional columns in your configuration as well. A conditional column value like { "default": "cjduyqawtl", "toProperty":"assortmentId"} will be parsed as all rows having the value cjduyqawtl for assortmentId, which triggers the same behavior.
Direct Assortment Item Updates vs Publish¶
Overview¶
When loading assortment item data, the loader provides two approaches for updating assortment items:
- Publish Workflow (default) - Updates assortment items through the publish mechanism, generating full change history and triggering downstream processes
- Direct Loader Update - Updates assortment items directly without triggering the full publish workflow
Publish Workflow (Default Behavior)¶
By default, when you load assortment item data using the loader, it will use the publish workflow to update assortment items. This generates a complete change history and triggers all downstream processes.
Advantages:
- Complete Audit Trail - All changes are recorded in
AssortmentPublishChangehistory - Assortment Summaries - Summary statistics and aggregates are automatically recalculated
- Composite Assortment Updates - Composite assortments that depend on the updated assortment are automatically recalculated
- Event Triggers - The
assortment|publishevent is triggered, notifying downstream integrations and workflows - Version Tracking - Version names and comments can be associated with the changes
Direct Loader Update¶
You can opt to update assortment items directly in the database without going through the publish workflow by setting shouldSkipAssortmentPublish: true.
Advantages:
- Performance - Significantly faster than the publish workflow as it skips additional processing steps
- Lightweight - Reduced system overhead and resource consumption
- Simpler - Direct database updates without triggering complex event chains
Limitations:
- No Assortment History - Changes are not recorded in the
AssortmentPublishChangehistory - No Assortment Summaries - Summary statistics and aggregates are not automatically recalculated
- No Composite Assortment Updates - Composite assortments that depend on the updated assortment will not be automatically recalculated
- No Event Trigger for Publish - The
assortment|publishevent is not triggered, so downstream integrations and workflows will not be notified if they rely on this event. Triggers for assortment item changes are still emitted (e.g.assortment-item|create). - No Version Tracking - Version names and comments cannot be associated with the changes
Enabling Direct Updates¶
To use direct updates instead of the publish workflow, set shouldSkipAssortmentPublish: true in your loader configuration:
loadType:
- ITEM
- PROJECT_ITEM
- ASSORTMENT
shouldSkipAssortmentPublish: true
assortmentSplit:
fieldToSplitOn: season
values:
- value: "spring"
assortmentId: "someAssortmentId"
{
"loadType": [
"ITEM",
"PROJECT_ITEM",
"ASSORTMENT"
],
"shouldSkipAssortmentPublish": true,
"assortmentSplit": {
"fieldToSplitOn": "season",
"values": [
{
"value": "spring",
"assortmentId": "someAssortmentId"
}
]
}
}
When shouldSkipAssortmentPublish is true, the loader will:
- Update assortment items directly in the database
- Skip generating
AssortmentPublishChangerecords - Skip recalculating assortment summaries and aggregates
- Skip triggering composite assortment recalculations
- Skip emitting the
assortment|publishevent
Default Behavior
If shouldSkipAssortmentPublish is not specified or is set to false, the loader will use the publish workflow (the complete, history-tracked approach).
Enabling Direct Updates for All Loads (Feature Flag)¶
You can also enable direct updates for all loader processes in your organization by using a feature flag. Contact your VibeIQ administrator or support team to enable the LOAD_ASSORTMENT_SKIP_PUBLISH feature flag for your organization.
When this feature flag is enabled:
- All assortment item loads will use direct updates by default
- Individual loader processes can still opt-in to the publish workflow by setting
shouldSkipAssortmentPublish: falsein their configuration - This is useful for organizations that cannot modify their loader configuration for some reason. The feature flag is expected to be deprecated, so it is not intended for long-term use. The most robust way to ensure loads proceed as expected is to explicitly set the
shouldSkipAssortmentPublishparameter in your loader configuration.
When to Use Each Approach¶
Use Direct Loader Update when:
- Making frequent updates where full history is not required
- Performance is critical and you have a high volume of changes
- You don't need to trigger workflows on the
assortment|publishevent - You are working in isolated assortments without composite relationships
Use Publish Workflow when:
- You need a complete audit trail of all changes
- Downstream systems need to be notified of changes via events
- The assortment is part of a composite assortment structure
- You need to maintain summary statistics and aggregates
- Version control and change comments are important for your process
- You need to track who made changes and when
- You make updates to assortments infrequently and use large bulk updates rather than small, frequent updates