Getting Started With SCAYLE
Add Sustainability Badge
- Getting started
- Tech
Robert Merten
VP Tech
Now that we've setup the Storefront Boilerplate, let's use it to add a small feature to our shop.
Let's assume we want to indicate to customers if specific products are sustainable or not.
You might want to have multiple Attribute values to show which specific parts of your product are sustainable. For example, to indicate which products use sustainable materials, or which products were sourced through sustainable methods. For the sake of simplicity, we will define the overall product in this tutorial as "sustainable".
This is what the end result will look like:
As before, we will use the products.csv
to update our products with the sustainability Attribute Group.
Create this file at src/009_addSustainabilityAttributes.js.
const Papa = require("papaparse");
const fs = require("fs");
const SwaggerClient = require("swagger-client");
require("dotenv").config();
async function addSustainabilityAttribute() {
const client = await new SwaggerClient({
url: `https://${process.env.TENANT_KEY}.admin.api.scayle.cloud/api/admin/v1/admin-api.json`,
authorizations: {
accessToken: {
value: process.env.ADMIN_API_TOKEN,
},
},
});
}
addSustainabilityAttribute();
Error | Meaning |
---|---|
SYSTEM_ATTRIBUTE_GROUP_CANNOT_BE_UPDATED | System Attribute Group cannot be updated. |
SYSTEM_ATTRIBUTE_GROUP_CANNOT_BE_DELETED | System Attribute Group cannot be deleted. |
NAME_IS_NOT_UNIQUE | Attribute Group with name sustainable2 already exists |
ONLY_SUPPORTED_FOR_ADVANCED_TYPES | Structure is only supported for advanced types |
ADVANCED_TYPE_CAN_NOT_BE_SHARED | Attribute Group of advanced types can not be shared |
MISSING_BASE_LOCALE | The base locale must be provided |
INVALID_LOCALE | The provided locale does not exist |
Let's implement the updateAttribute
function to call the Admin API to add the Attribute Group to our products.
We don't need the product ids and can use the referenceKey we set earlier. Notice that we need to prefix the productIdentifier
with key=
to make sure the API doesn't expect the ID.
async function updateAttribute(client, product) {
let attribute = {
name: "sustainable",
type: "simple",
value: product.sustainable, // Either "true" or "false"
};
try {
let response = await client.apis.Attributes.updateOrCreateProductAttribute(
{ productIdentifier: `key=${product.referenceKey}` },
{ requestBody: attribute }
);
const createdAttribute = response.body;
console.info("Created Attribute:", createdAttribute);
} catch (error) {
console.error("Unable to update attribute", error.response.body.errors);
}
}
Navigate to Shops > My Shop >Products
and select Germany.
You can now filter for sustainable products.
const Papa = require("papaparse");
const fs = require("fs");
const SwaggerClient = require("swagger-client");
require("dotenv").config();
async function updateAttribute(client, product) {
let attribute = {
name: "sustainable",
type: "simple",
value: product.sustainable,
};
try {
let response = await client.apis.Attributes.updateOrCreateProductAttribute(
{ productIdentifier: `key=${product.referenceKey}` },
{ requestBody: attribute }
);
const createdAttribute = response.body;
console.info("Created Attribute:", createdAttribute);
} catch (error) {
console.error("Unable to update attribute", error.response.body.errors);
}
}
async function addSustainabilityAttribute() {
const client = await new SwaggerClient({
url: `https://${process.env.TENANT_KEY}.admin.api.scayle.cloud/api/admin/v1/admin-api.json`,
authorizations: {
accessToken: {
value: process.env.ADMIN_API_TOKEN,
},
},
});
const newAttributeGroup = {
name: "sustainable2",
frontendName: {
de_DE: "Sustainable",
en_GB: "Sustainable",
},
type: "simple",
isShared: true,
level: "product",
};
try {
const response = await client.apis.AttributeGroups.createAttributeGroup(
{},
{ requestBody: newAttributeGroup }
);
const createdAttributeGroup = response.body;
console.info("Created Attribute Group:", createdAttributeGroup);
} catch (error) {
console.error(
"Unable to create attribute group:",
error.response.body.errors
);
}
fs.readFile("./data/products.csv", "utf8", function (err, data) {
if (err) {
console.error("Error reading the CSV file:", err);
process.exit(1);
}
Papa.parse(data, {
header: true,
complete: function (results) {
console.log("Parsed results:", results.data);
for (const product of results.data) {
updateAttribute(client, product);
}
},
error: function (error) {
console.log("Unable to parse CSV", error);
},
});
});
}
addSustainabilityAttribute();
To add the badge we just created to our shop, let's first make sure we have all the necessary data. Note that the indexer might take a while to take up the new data.
Navigate to the following URL:
https://{YOUR_TENANT}.storefront.api.scayle.cloud/v1/products?shopId={SHOP_ID}&with=attr
There you should be able to see the sustainable attribute returned by the Storefront API:
Make sure that you choose a product that actually has the sustainable Attribute Group set to "true".
You can find the code for the product detail page here: pages/p/[slug].vue
The code for the badge should look like this:
<ProductBadge
v-if="product.isSoldOut"
:badge-label="
getBadgeLabel({ isSoldOut: product.isSoldOut })
"
/>
This badge will be displayed when a product is sold out. We will reuse this component to show if a product is sustainable.
The product data that we need is provided by useProductDetails.
The current code should look something like this:
const {
product,
activeVariant,
quantity,
availableQuantity,
hasOneSizeVariantOnly,
brand,
name: productName,
images,
breadcrumbs,
siblings,
hasSpecial,
price,
handleSelectedSize,
lowestPriorPrice,
fetching,
listingMetaData,
} = await useProductDetails()
We can find this composable at composables/useProductDetails.ts
This composable fetches the data via useProduct
.
const {
data: product,
error,
fetching,
} = await useProduct({
params: {
id: productId.value,
with: PRODUCT_WITH_PARAMS,
},
key: `useProduct-${productId.value}`,
})
PRODUCT_WITH_PARAMS
Defines which data is fetched from the product.
Let's head there at constants/product.ts
and add the sustainable Attribute Groupto things we want to fetch from the storefront API.
This is a performance optimization to limit the amount of data that is transferred. When building up your product detail page, make sure to only fetch the subset of product data you need to display the item to your user.
Let's add the sustainable Attribute Group.
export const PRODUCT_WITH_PARAMS: ProductWith = {
attributes: {
withKey: [
'color',
'brand',
'name',
'promotion',
'fastenerType',
'design',
'extras',
'material',
'print',
'careInstructions',
'fitting',
'upperLength',
'sleeveLength',
'shirtCut',
'shortsLength',
'trousersLength',
'skirtLength',
'neckline',
'trousersCut',
'sustainable', // Add this
],
},
// Further configuration
}
useProduct
should now return the attribute we want.
Before we can use return
of useProductDetails
let's add a variable called isSustainable
const isSustainable = computed(
() => getFirstAttributeValue(product.value?.attributes, 'sustainable')?.value,
)
getFirstAttributeValue
is a helper that will look for the sustainable Attribute Group and return its value. If it's not auto-imported in your environment, you might need to add it to the imports.
import {
type Variant,
type Value,
getCategoriesByRoute,
getBreadcrumbs,
getPrice,
getProductSiblings,
getVariantBySize,
getFirstAttributeValue, // Add this
} from '@scayle/storefront-nuxt'
Make sure to console.log
or to set a breakpoint frequently to check if the data is actually returned
Finally, we want to return the new variable like so:
return {
productId,
brand,
name,
price,
lowestPriorPrice,
siblings,
activeVariant,
hasOneSizeVariantOnly,
images,
hasSpecial,
handleSelectedSize,
availableQuantity,
quantity,
categories,
breadcrumbs,
fetching,
product,
listingMetaData,
isSustainable, // Add this
}
If we go back to the product detail page at pages/p/[slug].vue,
we receive the new value:
const {
product,
activeVariant,
quantity,
// ...
isSustainable, // Add this
} = await useProductDetails()
Now that we've gotten all the data we need, the only thing left to do is add the badge.
Below the already existing soldOut
badge, we can add our sustainability badge.
<ProductBadge
v-if="product.isSoldOut"
:badge-label="
getBadgeLabel({ isSoldOut: product.isSoldOut })
"
/>
// Add this
<ProductBadge
v-if="isSustainable"
badge-label="Sustainable"
:translate="false"
/>
In this example, we set translate
to false
. Normally you would set this up with a translation, so that you can support multiple languages in your shop.
For products that are sustainable (remember that we didn't define all products as sustainable), you should now see a badge on the right-hand side of the product detail page.
Getting Started With SCAYLE
Robert Merten
VP Tech