Three-step workflow
- Last updated on April 27, 2024
- •
- 6 minutes to read
Let's consider the example that your product is business cards, and you want customers to personalize it. Customers can select horizontal, vertical, or square format, and two types of style.
For this, you may create a three-step workflow. First, customers select a product variant, edit a design in Design Editor, and then approve the result.
Let's see how this workflow looks.
In this tutorial, you will learn how to create a three-step PIM workflow.
Planning
Let's start from planning your workflow. For this, you need to decide the quantity of steps and what widgets you need.
Steps
This workflow contains three steps:
The
Variant Selector
step. Here, a customer selects a product variant.The
Editor
step. In this step, a customer edits a design in the Design Editor.The
Approval
step. A customer approves the personalization result.
"steps": [
{
"name": "Variant Selector"
},
{
"name": "Editor"
},
{
"name": "Approval"
}
]
Widgets
Let's consider what widgets you need for this workflow:
design-editor
for customizing a design.variant-selector
for selecting a product variant.order
for creating an order.finish-group
for defining buttons and checkboxes at theApproval
step.steps
for hiding theFinish
button in the Navigation panel.slider
for representing a personalization result.
"widgets": [
{
"name": "editor",
"type": "design-editor",
"params": {...}
},
{
"name": "variant-selector",
"type": "variant-selector",
"params": {...}
},
{
"name": "order",
"type": "order",
"params": {...}
},
{
"name": "finish",
"type": "finish-group",
"params": {...}
},
{
"name": "steps",
"type": "steps",
"params": {...}
},
{
"name": "preview",
"type": "slider",
"params": {...}
}
]
Vars
Let's define variables for your workflow. The following syntax allows you to get a product ID, a product version ID, and a product filter ID from BackOffice.
"vars": {
"pimProductId": "{| Product.id |}",
"pimProductVersionId": "{| Product.productVersionId |}",
"pimProductFilterId": "{| Product.productFilterId |}"
}
Defining steps
Variant selector
The Variant Selector
step is the first step in this workflow. At this step, customers select a product variant by filters. For this, use the variant-selector
widget and embed it in the mainPanel
.
The variant-selector
widget shows both product variants and design variants. This widget uses the defined vars
and obtains the data about a product, variants, and filters.
{
"name": "variant-selector",
"type": "variant-selector",
"params": {
"productId": "{{ vars.pimProductId }}",
"productVersionId": "{{ vars.pimProductVersionId }}",
"productFilterId": "{{ vars.pimProductFilterId }}"
}
}
Editor
The Editor
step is the second step in this workflow file. At this step, customers personalize a design in the design-editor
widget. It is embedded in the mainPanel
.
Add the onActivate
event to show the preloader while loading the design-editor
and the design selected at the Variant selector
step.
{
"name": "Editor",
"mainPanel": {
"name": "editor"
},
"onActivate": [
"{{ #function main.showPreloader(true) }}",
"{{ #function $['editor'].commands.initial.execute($['editor'].params.initial) }}",
"{{ #function main.showPreloader(false) }}"
]
}
Design Editor
The design-editor
widget allows customers to personalize a design. Let's consider the basic settings.
The initial
command gets a selected design in the productDefinition
property from the variant-selector
widget. The editorConfig
property configures the editor and gets fonts from your tenant. In the rendering
object, you will define the output resolution, file format, and color space and enable safety lines.
{
"name": "editor",
"type": "design-editor",
"params": {
"initial": {
"autoCompile": false,
"showPreloader": true,
"productDefinition": "{{ $['variant-selector'].selectedVariant.designId}}",
"editorConfig": {
"initialMode": "Advanced",
"restoreProductOnReloadEnabled": false,
"fontList": {
"appFonts": [
"*"
]
},
"rendering": {
"hiResOutputDpi": 300,
"hiResOutputFileFormat": "pdf",
"hiResOutputColorSpace": "cmyk",
"proofImageSafetyLinesEnabled": false
}
}
}
}
}
Approval
At the Approval
step, customers approve the personalization result, and then create an order. For this, define the slider
and finish-group
widgets. Then, embed slider
in the mainPanel
and finish group
in the bottomPanel
.
{
"name": "3. Approval",
"mainPanel": {
"name": "preview"
},
"bottomPanel": {
"name": "finish"
}
}
Slider
The Slider
widget displays the personalization result. For this, slider
gets proof images from the design-editor
widget, and then creates columns to show design pages. You can also define style settings for this widget, for example, the background color and paddings.
{
"name": "preview",
"type": "slider",
"params": {
"style": {
"--au-widget-background": "#eee",
"--au-widget-padding": "8px"
},
"direction": "tile",
"rows": 1,
"columns": "{{Math.min(2,$['editor'].proofImageUrls.length)}}",
"containerColor": "#eee",
"images": {
"{{#each $['editor'].proofImageUrls.map(s=>s[0]) as imageUrl }}": {
"url": "{{imageUrl}}"
}
}
}
}
Finish group
This finish-group
widget represents the confirmation checkbox and the Add to cart button. When the user clicks this button, the widget saves the personalization result and renders hi-res images.
{
"name": "finish",
"type": "finish-group",
"params": {
"checkboxPrompt": "I have reviewed and approve my design.",
"value": false,
"checkboxEnabled": true,
"checkboxVisible": true,
"buttonText": "Add to cart",
"buttonClassStyle": "primary",
"onClick": [
"{{#function main.showPreloader(true, 'Creating print files...')}}",
"{{#function $['editor'].getHiResImages()}}",
"{{#function new Promise(res=> setTimeout(res,1000)) }}",
"{{#function main.showPreloader(false)}}"
]
}
}
Steps widget
The steps
widget allows you to hide the Finish button in the Navigation panel, which appears by default.
{
"name": "steps",
"type": "steps",
"params": {
"finishButton": {
"visible": "false"
}
}
}
Connecting steps
When you go from the Editor
step to the Approval
step, the workflow will render proof images and clear the confirmation checkbox. It is used for the situations when you decide to go back to the Editor
step to correct the result.
"onActivate": [
"{{#function $['editor'].getProofImages(800,800)}}",
"{{#function $['finish'].value = false}}"
]
Creating order
The order
widget creates an order in the e-commerce system, creates a project in Customer's Canvas, and finishes the personalization process. This widget passes high resolution images, SKU, and other related information.
{
"name": "order",
"type": "order",
"params": {
"data": {},
"sku": "{{ $['variant-selector'].selectedVariant?.storefrontProductVariantId || '' }}",
"props": {
"_stateId": [
"{{ $['editor'].stateId }}"
],
"_userId": "{{ $['editor'].userId }}",
"_hidden": {
"snapshot": "{{ main.editorState }}",
"images": "{{ $['editor'].proofImageUrls.map(u=>u[0]) }}",
"downloadUrls": "{{ $['editor'].hiResUrls }}",
"sku": "{{ $['variant-selector'].selectedVariant?.storefrontProductVariantId || '' }}",
"originalProductId": "{{ product.id.toString() }}",
"productVersionId": "{{ vars.pimProductVersionId }}"
}
}
}
}
Result
Let's consider how this three steps workflow looks.
{
"showSaveProjectButton": true,
"showOpenSavedProjectsButton": true,
"vars": {
"pimProductId": "{| Product.id |}",
"pimProductVersionId": "{| Product.productVersionId |}",
"pimProductFilterId": "{| Product.productFilterId |}"
},
"showSteps": true,
"widgets": [
{
"name": "editor",
"type": "design-editor",
"params": {
"initial": {
"autoCompile": false,
"showPreloader": true,
"productDefinition": "{{ $['variant-selector'].selectedVariant.designId}}",
"editorConfig": {
"initialMode": "Advanced",
"restoreProductOnReloadEnabled": false,
"fontList": {
"appFonts": [
"*"
]
},
"rendering": {
"hiResOutputDpi": 300,
"hiResOutputFileFormat": "pdf",
"hiResOutputColorSpace": "cmyk",
"proofImageSafetyLinesEnabled": false
}
}
}
}
},
{
"name": "steps",
"type": "steps",
"params": {
"finishButton": {
"visible": "false"
}
}
},
{
"name": "variant-selector",
"type": "variant-selector",
"params": {
"productId": "{{ vars.pimProductId }}",
"productVersionId": "{{ vars.pimProductVersionId }}",
"productFilterId": "{{ vars.pimProductFilterId }}"
}
},
{
"name": "order",
"type": "order",
"params": {
"data": {},
"sku": "{{ $['variant-selector'].selectedVariant?.storefrontProductVariantId || '' }}",
"props": {
"_stateId": [
"{{ $['editor'].stateId }}"
],
"_userId": "{{ $['editor'].userId }}",
"_hidden": {
"snapshot": "{{ main.editorState }}",
"images": "{{ $['editor'].proofImageUrls.map(u=>u[0]) }}",
"downloadUrls": "{{ $['editor'].hiResUrls }}",
"sku": "{{ $['variant-selector'].selectedVariant?.storefrontProductVariantId || '' }}",
"originalProductId": "{{ product.id.toString() }}",
"productVersionId": "{{ vars.pimProductVersionId }}"
}
}
}
},
{
"name": "finish",
"type": "finish-group",
"params": {
"checkboxPrompt": "I have reviewed and approve my design.",
"value": false,
"checkboxEnabled": true,
"checkboxVisible": true,
"buttonText": "Add to cart",
"buttonClassStyle": "primary",
"onClick": [
"{{#function main.showPreloader(true, 'Creating print files...')}}",
"{{#function $['editor'].getHiResImages()}}",
"{{#function new Promise(res=> setTimeout(res,1000)) }}",
"{{#function main.showPreloader(false)}}"
]
}
},
{
"name": "preview",
"type": "slider",
"params": {
"style": {
"--au-widget-background": "#eee",
"--au-widget-padding": "8px"
},
"direction": "tile",
"rows": 1,
"columns": "{{Math.min(2,$['editor'].proofImageUrls.length)}}",
"containerColor": "#eee",
"images": {
"{{#each $['editor'].proofImageUrls.map(s=>s[0]) as imageUrl }}": {
"url": "{{imageUrl}}"
}
}
}
}
],
"steps": [
{
"name": "1. Variant Selector",
"mainPanel": {
"name": "variant-selector"
}
},
{
"name": "2. Editor",
"mainPanel": {
"name": "editor"
},
"onActivate": [
"{{ #function main.showPreloader(true) }}",
"{{ #function $['editor'].commands.initial.execute($['editor'].params.initial) }}",
"{{ #function main.showPreloader(false) }}"
]
},
{
"name": "3. Approval",
"mainPanel": {
"name": "preview"
},
"bottomPanel": {
"name": "finish"
},
"onActivate": [
"{{#function $['editor'].getProofImages(800,800)}}",
"{{#function $['finish'].value = false}}"
]
}
]
}