Third Party Scripts in Headless E-Commerce
This document was born from the serious lack of documentation for third party scripts in headless sites. Most of the existing docs are written for Shopify, or similar sites; and obviously those docs can be applied to the kind of webpages we develop, but sometimes there are caveats not mentioned anywhere that will make anyone spend hours and hours trying to figure out why this f****ng script isn’t working.
The idea is to keep this doc maintained and up to date. We all hate writing documentation, but if you come across some weird way of implementing something weird, when adding a third party script, try to add your experience here.
For Firefox users: always keep in mind that if a script is not being loaded it might be because Firefox blocks all the requests to tracking scripts, and well, in e-commerce 90% of the scripts are tracking something.
Also always remember to add third party scripts with async or defer attributes.
Note: it’s more than likely that if there are examples here they will be made with NuxtJS in mind. But you can still extrapolate that to NextJS or whatever framework being used
Table of Contents:
1. Attentive
Offers mobile texting (ads) based on things bought or seen. Everytime the customer buys or sees a product an event is fired to Attentive API using the SDK loaded with the script. As of (09/06/2022) if you are working from LATAM then you will never make this script work. Attentive doesn’t work for LATAM and that’s it. You still can implement it and then use a VPN to test it or if the client is from the USA they can test it as well.
Installation
Just add the following to your nuxt.config. ${storename} is the store name Attentive assigned to your client.
{
src: 'https://cdn.attn.tv/${storename}/dtag.js',
defer: true,
body: true
},
Implementation:
This example implementation was done using vue-composition-api hence the product.value in each field, you can adapt that to whatever you are using.
Product view
window.attentive.analytics.productView({
items: [
{
productId,
productVariantId: product.value.selectedVariant.id,
name: product.value.title,
productImage: product.value.featuredMedia?.src,
category: product.value.productType,
price: {
value: product.value.selectedVariant.price,
currency: product.value.selectedVariant.priceCurrency,
},
quantity: 1,
},
],
user: {
phone: user?.value?.phone || "",
},
});
Add To Cart
window.attentive.analytics.addToCart({
items: [
{
productId,
productVariantId: variantId,
name: product.title,
productImage: selectedVariant.featuredMedia.src,
category: product.productType,
price: {
value: selectedVariant.price,
currency: selectedVariant.priceCurrency,
},
quantity: 1,
},
],
cart: {
cartId: "cart-1",
cartCoupon: "",
},
user: {
phone: user?.phone || "",
},
});
2. Wunderkind
Just marketing.
Installation for nuxt.js (09/06/2022)
Add the following function as a client-side plugin. The ${id} should be provided by the client.
(function (d) {
const e = d.createElement("script");
e.src = d.location.protocol + "//tag.wknd.ai/${id}/i.js";
e.async = true;
d.getElementsByTagName("head")[0].appendChild(e);
})(document);
3. Brandzooka Tracking Pixel
More marketing. Conversions (I think) tracking pixel. For the checkout and also for the headless site.
Installation
For headless and the checkout the installation is the same. The example will be of a nuxt.js app but you can still use that for the checkout in the checkout.liquid theme file. Just add the following as a client-side plugin in nuxt.js and for the checkout wrap this in \ tags with a type=”text/javascript” attribute and put it there. \${id1} and ${id2} should be provided by the client
const brandzookaScript = document.createElement('script')
brandzookaScript.src = 'https://js.adsrvr.org/up_loader.1.1.0.js'
brandzookaScript.type = 'text/javascript'
const callback = function () {
ttd_dom_ready(function () {
if (typeof TTDUniversalPixelApi === 'function') {
const universalPixelApi = new TTDUniversalPixelApi()
universalPixelApi.init(
${id1},
[${id2}],
'https://insight.adsrvr.org/track/up'
)
}
})
}
brandzookaScript.onload = callback
document.head.appendChild(brandzookaScript)
4. Back In Stock
Notifies customers subscripted when a product is back in stock. This one does have well written documentation here. Just remember to pass the productId and variantId from below decoded
BIS.create(email, variantId, productId, [attributes]);
Installation
Just add the script to the nuxt.config. ${shopifyStoreName} should be something like shopifystore.myshopify.com
{
src: 'https://app.backinstock.org/bis/widget/3108_1649082678.js?v=6&shop=${shopifyStoreName}',
defer: true
}
5. Yotpo
Yotpo includes several things: Yotpo Reviews & Rating, Yotpo UGC, Yotpo Loyalty & Rewards.
Yotpo Reviews & Rating
Installation
Adding this to nuxt.config as a script should be enough:
{
src: `https://staticw2.yotpo.com/${process.env.YOTPO_API_KEY}/widget.js`,
defer: true,
mode: 'client',
body: true,
type: 'text/javascript',
charset: 'utf-8'
},
Implementation for reviews
Just add this div where you want to show the reviews. PDP usually. productId is the decoded id from the product
<div
class="yotpo yotpo-main-widget"
:data-product-id="productId"
:data-name="product.title"
:data-url="'https://www.yourshop.com/products/' + product.handle"
:data-image-url="product.featuredMedia ? product.featuredMedia.src : ' '"
></div>
Implementation for ratings
Just add this div where you want to show the reviews. PDP usually. productId is the decoded id from the product
<div class="yotpo bottomLine" :data-product-id="productId"></div>
Run this to refresh and show the widgets
window.yotpo?.refreshWidgets();
Installation alternative
If for some reason you don’t want to install the script and you want to have something more customizable you still can get the data from Yotpo’s API. Gist example here.
Yotpo UGC
Installation
The same installation used for the Yotpo Reviews & Rating
Implementation:
Add this wherever you want to show the gallery. Replace gallery-id with your id
<div class="yotpo yotpo-pictures-widget" data-gallery-id="gallery-id"></div>
Yotpo Loyalty & Rewards
This one can include several modules in the headless site and also in the checkout. If it’s possible, try to stay away from implementing the Free Product Module (as of 10/06/2022 we couldn’t implement it, and we’re waiting on Yotpo’s engineer response on how to do it).
Yotpo Rewards Page Implementation
I’m going to leave a gist example here on how to implement a rewards page using NuxtJS. This case contemplates users being authenticated and also not being authenticated. This is handled using the functions loadYotpoScript, cleanYotpoElements, reloadYotpoElements. This implementation also considers the “rewiring” of the buttons. Originally buttons (authentication related buttons like Join Now or Login) behavior is redirect to page/login or page/register. This rewiring makes this button trigger the account drawer to register or login, all of this is made through the changeAuthButtonBehavior . Also for this case there were some Sign Up buttons that only showed when the user hover over a card the rewiring for this is done using the initMutationObserver function defined inside changeAuthButtonBehavior .
Also don’t forget to add this div so Yotpo knows if the user is logged in or not. You could add it globally, in your layout or something like that, or just in the page where you need it.
<div
v-if="user"
id="swell-customer-identification"
data-authenticated="true"
:data-email="user.email"
:data-id="userId"
style="display: none"
></div>
Yotpo Rewards Page with Free Product Module Implementation
If you couldn’t avoid staying away from the Free Product Module this gist could be a nice place to start. Keep in mind that this doesn’t work and we have no idea on how to make it work. Contact Yotpo support.
Yotpo Coupons Dropdown in Shopify Checkout Implementation
Add the following to your checkout.liquid file
<!-- Yotpo dropdown script -->
<script src=`https://cdn-widgetsrepository.yotpo.com/v1/loader/${apiKey}` async></script>
<!-- Yotpo identification -->
<div
id="swell-customer-identification"
data-authenticated="true"
data-email="{{ customer.email }}"
data-id="{{ customer.id }}"
style="display:none;">
</div>
<!-- add this div wherever you want it to appear -->
<div class="yotpo-widget-instance" data-yotpo-instance-id="119215"></div>
6. Hotjar
Analytics
Installation
Add this as a client-side plugin in nuxt.config
export default () => {
if (typeof window !== "undefined") {
(function (h, o, t, j, a, r) {
h.hj =
h.hj ||
function () {
(h.hj.q = h.hj.q || []).push(arguments);
};
h._hjSettings = { hjid: `${id}`, hjsv: 6 };
a = o.getElementsByTagName("head")[0];
r = o.createElement("script");
r.async = 1;
r.src = t + h._hjSettings.hjid + j + h._hjSettings.hjsv;
a.appendChild(r);
})(window, document, "https://static.hotjar.com/c/hotjar-", ".js?sv=");
}
};
7. Klaviyo Subscribe
Installation
Add the next to your nuxt.config scripts
{
src: '//www.klaviyo.com/media/js/public/klaviyo_subscribe.js',
defer: true
},
Implementation:
Leaving gist with example here