App Widget in Storefront
Once the merchant has inserted the app widget into their page, the app widget will be rendered in the following way:
-
Each inserted app widget will have a section div in storefront:
-
The section div will contain the following elements:
- Script element with the merchant's app widget settings in JSON format
- HTML element
Example:
<!-- custom tag name -->
<section-component>Awesome HTML</section-component>
Output example:
<div id="shopline-section-{section_id}" class="shopline-section">
<!-- Merchant settings JSON -->
<script type="text/json" data-app-widget-type="app-widget_{appId}_{widget_identifier}">
{"id": "xxx", "settings": {}, "blocks": []}
</script>
<!-- Optional App Widget HTML -->
<section-component>Awesome HTML</section-component>
</div>
Merchant Settings JSON
The merchant settings configured in SHOP Builder will be rendered in the storefront as JSON object in a script tag.
The script tag will contain the attribute data-app-widget-type
with the value constructed in this format:
app-widget_{app_identifier}_{widget_identifier}
app_identifier
is{app_ID}
for Release version, and{app_ID}_TESTING
for Development version{widget_identifier}
will be the App Widgetname
set in the Developer Portal (See here for more details).
The JSON data contains the following attributes:
id
(string): The section id, where you can use it to get the section divsettings
(object): The settings merchant set in SHOP Builderblocks
(array of objects): The block settings merchant set in SHOP Builder
You can use the following example JS code to get the corresponding section div & settings data for every section of your app widget:
class SectionComponent extends HTMLElement {
constructor() {
super();
// To get section container dom
this.$sectionContainer = this.closest('[id^="shopline-section-"]');
// To get section data script
// Please replace {widgetType}
var $script = this.$sectionContainer.querySelector('script[data-app-widget-type*="{widgetType}"]');
var scriptContent = $script.innerHTML;
// To get section data
this.sectionData = JSON.parse(scriptContent);
// do something ...
}
};
// Binding web component
// Please replace the first parameter with your custom tag name
customElements.define('section-component', SectionComponent);
The example is just for reference. You can also get data through JS script according to the rules.
Settings Format
Every setting will have the setting ID
as the key, and the corresponding setting as the value.
The setting ID is the ID you defined for your setting in the schema. For example, if your schema is the following:
{
...,
"settings": [
{
"id": "setting-id",
"type": "text"
}
]
}
The setting ID will be the setting-id
.
The value format varies on the setting type used. For example, if the setting type is range
, the setting value will be an integer. If the setting type is product_picker
, the setting value will be an object containing the product
attributes.
The full list of setting types format can be found here, in the Return
section of each setting type.
__original
Field
__original
FieldFor specific setting types, besides the setting field, there will be also an {setting_id}__original
field.
For example, for product_picker
setting type, the setting JSON is like this:
{
"settings": [
{
"product-picker-setting-id": {
"id": "67279e000000000000000000",
...
},
"product-picker-setting-id__original": "67279e000000000000000000"
}
]
}
The __original
field allows you to distinguish between the case where merchant haven't selected any resources, and the case where the resource is already unpublished / deleted.
For example, for product_picker
type, you can use the following logic to distinguish and handle different cases:
// Pseudo code only
if product == null && product___original != null {
// Product is unpublished / deleted
// Maybe display placeholder
...
} else if product == null {
// No product has been chosen
// Maybe hide the widget
...
} else {
// display widget as usual
...
}
Below is the behavior of every special setting type under different scenarios:
Setting Type | Normal Case | Resource Not Selected by Merchant | Resource Unpublished / Deleted |
---|---|---|---|
product_picker | product : Object of product attributesproduct__original : String (product ID) | product : nullproduct__original : null | product : nullproduct__original : String (product ID) |
products_picker | products : Product[] products__original : String[] (product IDs) | products : [] products__original : [] | products : [] products__original : String[] (product IDs) |
collection_picker | category : Object of category attributescategory__original : String (category ID) | category : nullcategory__original : null | category : nullcategory__original : String (category ID) |
image_picker (with is_multi_lang: true ) | image : Object of image URLsimage__original : Object of image URLs in different locales(key: locale, value: Object of image URLs) | image : nullimage__original : {[locale_key]: {}} (e.g. {en: {}, ...} ) | / |
image_picker (with is_multi_lang: false ) | image : Object of image URLsimage__original : Object of image URLs | image : nullimage__original : {} | / |
Image URLs
We have provided two image URLs, one for 800x, and one for 1200x in advance for images type resources (i.e. image from image_picker
type, and the product image in product
).
{
"settings": {
"image": {
"url": {
"800x": "https://shoplineimg.com/629446751ffcc7000750101f/5d1c83fe9fc3a000263a58e9/800x.webp?source_format=jpg",
"1200x": "https://shoplineimg.com/629446751ffcc7000750101f/5d1c83fe9fc3a000263a58e9/1200x.webp?source_format=jpg"
}
}
}
}
In case you need a different resolution of the image, you can replace the 800x
part with the resolution you want.
i.e. If the URL for 800x
is https://shoplineimg.com/629446751ffcc7000750101f/5d1c83fe9fc3a000263a58e9/800x.webp?source_format=jpg
, the URL for 1500x
will be https://shoplineimg.com/629446751ffcc7000750101f/5d1c83fe9fc3a000263a58e9/1500x.webp?source_format=jpg
.
Please note that we do not recommend using very high resolution of images, as it may impact storefront performance.
Product
For product_picker
/ products_picker
type, the info of the selected product(s) will be included in the JSON data in SHOP. For every product, they will have the following attribute:
Attribute | Type | Description |
---|---|---|
id | String | Product ID |
sku | String | Product SKU |
title | String | Product Title |
image | Image | The first product image (See above for Image format) |
url | String | The relative URL of the product |
price | String | Price of the product (with currency) |
available | Boolean | Returns true if a product is available for purchase.Returns false if all of the products variants' inventory quantity values are zero or less, and they are not set to "unlimited quantity" |
Example code:
{
"id": "62946cf094ba250001d4dc37",
"sku": "",
"title": "Example Product",
"image": {
"url": {
"800x": "https://shoplineimg.com/629446751ffcc7000750101f/5d1c83fe9fc3a000263a58e9/800x.webp?source_format=jpg",
"1200x": "https://shoplineimg.com/629446751ffcc7000750101f/5d1c83fe9fc3a000263a58e9/1200x.webp?source_format=jpg"
}
},
"url": "https://example-handle.shoplineapp.com/products/example-product",
"price": "HK$60.00",
"available": false
}
Category
For collection_picker
type, the info of the selected category will be included in the JSON data in SHOP. Every category will have the following attribute:
Attribute | Type | Description |
---|---|---|
id | String | Category ID |
title | String | Category Title |
url | String | URL of the category |
products | Array of Product | List of products in this category (See above for the Product format) |
Example code:
{
"id": "6294467829a34600181c3696",
"title": "Featured Products",
"url": "https://bookstore846.shoplineapp.com/categories/6294467829a34600181c3696?draft=true&amp;debug=true&draft=true&debug=true",
"products": [
{
"id": "62946cf094ba250001d4dc37",
"sku": "",
"title": "Example Product",
"image": {
"url": {
"800x": "https://shoplineimg.com/629446751ffcc7000750101f/5d1c83fe9fc3a000263a58e9/800x.webp?source_format=jpg",
"1200x": "https://shoplineimg.com/629446751ffcc7000750101f/5d1c83fe9fc3a000263a58e9/1200x.webp?source_format=jpg"
}
},
"url": "https://example-handle.shoplineapp.com/products/example-product",
"price": "HK$60.00",
"available": false
}
]
}
Updated 26 days ago