docs
  1. SCAYLE Resource Center
  2. Getting started
  3. Quick Start
  4. Create a Sustainability Badge

Create a Sustainability Badge

General

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:

Add sustainability Attribute Group

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();
ErrorMeaning
SYSTEM_ATTRIBUTE_GROUP_CANNOT_BE_UPDATEDSystem Attribute Group cannot be updated.
SYSTEM_ATTRIBUTE_GROUP_CANNOT_BE_DELETEDSystem Attribute Group cannot be deleted.
NAME_IS_NOT_UNIQUEAttribute Group with name sustainable2 already exists
ONLY_SUPPORTED_FOR_ADVANCED_TYPESStructure is only supported for advanced types
ADVANCED_TYPE_CAN_NOT_BE_SHAREDAttribute Group of advanced types can not be shared
MISSING_BASE_LOCALEThe base locale must be provided
INVALID_LOCALEThe provided locale does not exist

Add Attribute Group to our products

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);
  }
}

In the SCAYLE Panel

Navigate to Shops > My Shop >Products and select Germany.

You can now filter for sustainable products.

Full Code

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();

Add badge to product detail page

Storefront API

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".

Product detail page

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()

Fetch the data

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
}

Receive new value

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()

Add the badge

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.

Final result

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.

Further education - SCAYLE Academy