Skip to main content

Adding a Dynamic Sales Announcement Banner in Storefront: A Developer’s Guide to Using ScriptTag Bindings in Fynd Themes

In this document, we will learn how to add a discount banner to the Storefront to alert our customers of ongoing sale. We will achieve this using Storefront ScriptTag Bindings which injects script tags into the theme to provide custom functionalities.

Prerequisites

  • Ensure that you have created an extension. Refer to Get Started for more details.
  • Ensure that you have created a theme. Refer to Create a Theme for more details.

This tutorial is divided into two sections:

  1. Create a ScriptTag Binding
    Insert custom JavaScript code within script tag in an extension in Fynd Partners portal.
  2. Apply Bindings to Theme

Create a ScriptTag Binding

Do the following steps to create a ScriptTag bindings:

  1. Login to Fynd Partners.
  2. In the left pane, click Extensions and select the extension you've created.
  3. Go to the Extension Setup and ensure that the Extension URL and permissions are correctly configured.
  4. In the Bindings section, click Manage.
  5. In the upper-right corner of the window, click Add to create new Bindings.
  6. Select Storefront in Interface Area dropdown list.
  7. Select ScriptTag from the Binding Type dropdown list.
  8. Enter a name for the Bindings.
  9. Copy and paste the following code in the Wrapper Code input:
<script>
document.addEventListener('DOMContentLoaded', function () {
const announcementData = {
title: "Exclusive Deal – 50% Off for 24 Hours!",
marginRight: "10px",
borderRadius: "5px",
width: "100%",
height: "50px",
startDate: "2024-12-24T00:00:00", //Update with the correct values before implementation
endDate: "2024-12-25T23:59:59", //Update with the correct values before implementation
backgroundColor: "#970747",
titleColor: "#ffffff",
};

const isAnnouncementActive = (startDate, endDate) => {
const now = new Date();
const start = new Date(startDate);
const end = new Date(endDate);
return now >= start && now <= end;
};

const displayAnnouncementBanner = (data) => {
const container = document.getElementById('announcement-banner');
if (!container) {
console.error('Container for the announcement banner not found.');
return;
}

if (container.querySelector('.announcement-content')) {
console.log('Announcement already present. Skipping rendering.');
return;
}

if (isAnnouncementActive(data.startDate, data.endDate)) {
const announcement = document.createElement('div');
announcement.classList.add('announcement-content');
announcement.innerText = data.title;
announcement.style.marginRight = data.marginRight;
announcement.style.borderRadius = data.borderRadius;
announcement.style.width = data.width;
announcement.style.height = data.height;
announcement.style.backgroundColor = data.backgroundColor;
announcement.style.color = data.titleColor;
announcement.style.display = "flex";
announcement.style.alignItems = "center";
announcement.style.justifyContent = "center";
announcement.style.boxShadow = "0px 4px 6px rgba(0, 0, 0, 0.1)";
announcement.style.padding = "10px";
announcement.style.border = "1px solid black";
announcement.style.fontWeight = "bold";
announcement.style.fontSize = "16px";

container.appendChild(announcement);
console.log('Announcement banner rendered.');
} else {
console.log('Announcement is not active at this time.');
}
};

const container = document.getElementById('announcement-banner');
if (container) {
var observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
console.log('Mutation detected:', mutation);
});
displayAnnouncementBanner(announcementData);
});

observer.observe(container, { childList: true });

setTimeout(() => {
observer.disconnect();
console.log('Observer disconnected to prevent infinite loop.');
}, 1000);
}

setInterval(() => {
const container = document.getElementById('announcement-banner');
if (container && !container.querySelector('.announcement-content')) {
console.log('Announcement missing. Re-rendering.');
displayAnnouncementBanner(announcementData);
}
}, 5000);
displayAnnouncementBanner(announcementData);
});
</script>

<div id="announcement-banner" style="border: 1px solid red;"></div>
Understanding the Code

Please read the explanation section to understand how the wrapper code works.

  1. Select Allow on all pages checkbox if want to show the bannner in all the pages.
  2. Select where you need to show the product highlight from the dropdown list.
  3. Click Add.

You will see a success notification when the Bindings are successfully created.

Apply Bindings to Theme

Once you've created the ScriptTag Binding, you need to add it to the storefront. In this example, we will add the announcement banner to the header.

  1. Login to Fynd Commerce.
  2. Navigate to the desired sales channel.
  3. Go to AppearanceThemes.
  4. Navigate to the theme where you need to add the announcement banner and click Edit. The Theme Editor page opens.
  5. In the left pane, go to SettingsHeader Bindings.
  6. Click + Add Section and navigate to Extension.
  7. In the Extensions section, click Add.
  8. Choose the Extension for which you have created the Bindings.
  9. Select the Binding you created in the previous step.
  10. Click Save.
  11. Verify that the announcement banner appears in the correct position on the storefront.

Test the Banner

Header Announcement Banner

Well Done

You have successfully embedded an announcement banner inside the header of your theme using ScriptTag Binding.

A Deep Dive into Wrapper Code

Announcement Data

const announcementData = {
title: "Flash Sale - Up to 50% Off!",
marginRight: "10px",
borderRadius: "5px",
width: "100%",
height: "50px",
startDate: "2024-12-23T00:00:00", //Update with the correct values before implementation
endDate: "2025-12-24T23:59:59", //Update with the correct values before implementation
backgroundColor: "#f8d7da",
titleColor: "#721c24",
};
  • This object contains the properties required to configure the announcement banner, such as:
    • title: The announcement text.
    • startDate and endDate: The period when the announcement should be active.
    • Styling properties: backgroundColor, titleColor, width, height, etc.

Check if the Announcement is Active

The isAnnouncementActive function compares the current date and time against the provided boundaries (startDate and endDate) and ensures that the banner is displayed only during the given sale period.

  • If the current date is equal to or lies between startDate and endDate, the function returns true, signaling that the announcement should be shown.
  • If the current date falls outside this range, it returns false, suppressing the announcement.
const isAnnouncementActive = (startDate, endDate) => {
const now = new Date();
const start = new Date(startDate);
const end = new Date(endDate);
return now >= start && now <= end;
};

Display the Banner

The displayAnnouncementBanner function ensures the existence of the #announcement-banner in the DOM and checks if an announcement is already present by looking for .announcement-content. If an announcement exists, it skips rendering to prevent duplication. If not, it forms the announcement banner by creating a div element and applying styles and text from announcementData. Finally, it appends this newly created announcement to the #announcement-banner container.

const displayAnnouncementBanner = (data) => {
const container = document.getElementById("announcement-banner");
if (!container) {
console.error("Container for the announcement banner not found.");
return;
}

if (container.querySelector(".announcement-content")) {
console.log("Announcement already present. Skipping rendering.");
return;
}

if (isAnnouncementActive(data.startDate, data.endDate)) {
const announcement = document.createElement("div");
announcement.classList.add("announcement-content");
announcement.innerText = data.title;
// Apply styles
announcement.style.marginRight = data.marginRight;
announcement.style.borderRadius = data.borderRadius;
announcement.style.width = data.width;
// ...
announcement.style.fontSize = "16px";

container.appendChild(announcement);
console.log("Announcement banner rendered.");
} else {
console.log("Announcement is not active at this time.");
}
};

Mutation Observer

This function monitors the #announcement-banner for changes to its child elements, such as additions or removals of content. If any modifications are detected, it triggers displayAnnouncementBanner to ensure the announcement is re-rendered if necessary. To avoid an infinite loop from continuous DOM updates, the observer automatically disconnects after one second, ensuring efficient and controlled handling of DOM changes.

var observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
console.log("Mutation detected:", mutation);
});
displayAnnouncementBanner(announcementData);
});

observer.observe(container, { childList: true });

setTimeout(() => {
observer.disconnect();
console.log("Observer disconnected to prevent infinite loop.");
}, 1000);

Periodic Check with setInterval

This mechanism ensures the announcement banner is consistently displayed, even if an external script accidentally removes the #announcement-banner. Checking every five seconds for the presence of .announcement-content within the container guarantees that the announcement remains visible. If the content is missing, the function calls displayAnnouncementBanner to recreate and restore the announcement banner, maintaining uninterrupted communication with users.

setInterval(() => {
const container = document.getElementById("announcement-banner");
if (container && !container.querySelector(".announcement-content")) {
console.log("Announcement missing. Re-rendering.");
displayAnnouncementBanner(announcementData);
}
}, 5000);

Initial Render

The displayAnnouncementBanner function is called to ensure that the announcement is displayed immediately when the page loads.

displayAnnouncementBanner(announcementData);

Add the Container

The HTML element with the id announcement-banner is added at the end.

<div id="announcement-banner" style="border: 1px solid red;"></div>

Was this section helpful?