Setting Up the Extend Cart Offers
Overview
This article covers inserting the logic and layout code for the Extend cart offers component
Est. Time of Completion: 1:30 hour(s)
Create extend.js
- Go to /assets/js/theme/ and create a new file named
extend.js
. Paste the snippet below inside of it:
// initializeCartOffer()
// Initializes cart offer div tag elements with createAjaxOfferElements() then renders the buttons using Extend sdk
export function initializeCartOffers() {
// Ensuring Extend and ExtendBigCommerce are on the window before running
if (window.Extend && window.ExtendBigCommerce) {
// Slice - utility use
var slice = Array.prototype.slice;
/**********************/
/* util functions */
/**********************/
// FindAll function handles browser compatability issues for querySelectorAll
function findAll(element) {
var items = document.querySelectorAll(element);
return items ? slice.call(items, 0) : [];
}
// addPlanToCart injects offers into cart using ExtendBigCommerce SDK, taking in params
function addPlanToCart(sku, plan, quantity, cart) {
ExtendBigCommerce.addPlanToCart(
{
sku: sku,
plan: plan,
quantity: quantity,
cart: cart,
},
function (err) {
if (err) {
return;
} else {
return window.location.reload();
}
}
);
}
// Get's updated cart object
ExtendBigCommerce.getCart(function (error, cart) {
if (cart) {
// Run normalization
ExtendBigCommerce.normalizeCart(
{ cart: cart, balance: true },
function (err, data) {
if (data && data.updates) {
if (Extend.analytics) {
return window.dispatchEvent(
new CustomEvent("normalization", {
detail: { updates: data.updates },
})
);
} else {
window.location.reload();
}
}
}
);
// Initial empty state
var planToName = {};
// Goes through customItems grabbing the warranties and maps the productName to the warranty id in planToName
cart.lineItems.customItems.forEach(function (cItem) {
if (cItem && cItem.sku && cItem.sku.indexOf(";xtd;") > -1) {
var customId = cItem.id;
var sku = cItem.sku.split(";xtd;")[1];
var product = cart.lineItems.physicalItems.find(function (pItem) {
if (pItem.sku === sku) {
return pItem.name;
}
});
if (product && product.name) {
planToName[customId] = product.name;
}
}
});
// Find all plan items, and display product information
findAll("#extend-plan-item").forEach(function (el) {
var cartItemId = el.getAttribute("data-extend-itemid");
if (planToName[cartItemId]) {
el.innerText = "For: " + planToName[cartItemId];
}
});
// Find all cart offers and render the instance
findAll("#extend-cart-offer").forEach(function (el) {
var sku = el.getAttribute("data-extend-sku");
var quantity = el.getAttribute("data-extend-quantity");
var itemId = el.getAttribute("data-extend-item-id");
if (!sku) {
return;
}
// If there's already an instance or warranty is already in cart do not render offer
if (
Extend.buttons.instance(el) ||
ExtendBigCommerce.warrantyAlreadyInCart(sku, cart)
) {
return;
}
// Cart offer render
Extend.buttons.renderSimpleOffer(el, {
referenceId: sku,
onAddToCart: function (offer) {
// If there's only one item call addPlanToCart immediately
if (cart.lineItems.physicalItems.length === 1) {
addPlanToCart(sku, offer.plan, quantity, cart);
return;
}
// Show loading overlay
document
.querySelector("[data-cart] .loadingOverlay")
.setAttribute("style", "display: block");
// Find cart item, and get id and options from cartItem
var cartItem = cart.lineItems.physicalItems.find(
(it) => it.id == itemId
);
var cartId = cart.id;
var options = cartItem.options.reduce((optArray, opt) => {
var optId = opt.nameId;
var optValue = opt.valueId === null ? opt.value : opt.valueId;
return (optArray = [
...optArray,
{ optionId: optId, optionValue: optValue },
]);
}, []);
// For multiple items we have to remove the cart items, and add them back with respective plans so it shows the plan underneath the respective product
ExtendBigCommerce.deleteCartItem({ cartId, itemId }, function () {
ExtendBigCommerce.addCartItem(
{
cartId: cartId,
productId: cartItem.productId,
variantId: cartItem.variantId,
quantity: quantity,
optionSelections: options || [],
},
function () {
addPlanToCart(sku, offer.plan, quantity, cart);
}
);
});
},
});
});
}
});
}
}
// initializeAftermarket()
// Initializes post purchase lead modals when the app loads if we find a leadToken in the URL
export function initializeAftermarket() {
if (window.Extend && window.ExtendBigCommerce) {
function getQueryParam(name) {
var results = new RegExp("[?&]" + name + "=([^&#]*)").exec(
window.location.href
);
if (results == null) {
return null;
}
return decodeURI(results[1]) || 0;
}
// Searches URL for both leadToken or leadtoken and sets it to the leadToken variable
let leadToken = getQueryParam("leadToken")
? (leadToken = getQueryParam("leadToken"))
: (leadToken = getQueryParam("leadtoken"));
// If leadToken show modal containing lead offer
if (leadToken) {
window.Extend.aftermarketModal.open({
leadToken,
onClose: function (plan, product, quantity) {
if (plan && product) {
ExtendBigCommerce.addPlanToCart(
{
sku: product.id,
plan,
quantity,
leadToken,
},
function (err, data) {
if (err) {
console.error(err);
return;
} else if (!data || !data.cartUrl) {
window.location = "/cart.php";
} else {
window.location = data.cartUrl;
}
}
);
}
},
});
}
}
}
Import & Invoke initializeCartOffers Function
- Open the file /assets/js/theme/cart.js and copy the snipet below and paste it at the top of the file, right under all the other import statements:
// Extend - Import initializeCartOffers()
import { initializeCartOffers } from './extend.js';
// Extend - End Code
- In the same file, find the
onReady()
function inside theCart
class add the snippet below to invoke the function:
// Extend - Initialize cart offers when cart is initialy loaded
initializeCartOffers();
// Extend - End Code
Handle Cart Change
When the cart changes, we will need to invoke our initializeCartOffers() to ensure Extend renders correctly within the cart again.
- In the same file, scroll down and find the
utils.api.cart.getContent()
function. Copy the snippet below to invoke the function every time the cart updates:
// Extend - Initialize Cart Offers after the cart update
initializeCartOffers();
// Extend - End Extend Code
Style warranties in cart
Now that we can add warranties to the cart, we need to ensure they're styling correctly following the instructions below.
- Open the file /templates/components/cart/content.html
- Copy the snippet below:
<!-- Extend - Add Extend Logo for Warranties --> {{else if type '==' 'Custom'}} <img class="cart-item-fixed-image" data-sizes="auto" src="{{cdn 'img/extend_logo.png'}}" data-src="{{cdn ../theme_settings.default_image_extend}}" alt="Extend Protection Plan" title="Extend Protection Plan" /> <!-- Extend - End Extend Code -->
- Find the code
{{#if type '==' 'GiftCertificate'}}
and paste the snippet after the<img>
element, but before the closing{{else}}
statement:
- In the same file, find the block that starts with
{{#if brand.name}}
. Locate the<h2>
element containing the<a>
tag and delete the whole of the<h2>
and all it's contents. - Then copy and paste in the snippet below, which will replace the
<h2>
and<a>
we previously removed:
<!-- Extend - Remove links for warranties -->
{{#if type '==' 'Custom'}}
<h4 class="cart-item-name"><p>{{name}}</p></h4>
{{else}}
<h2 class="cart-item-name">
<a class="cart-item-name__label" href="{{url}}">{{name}}</a>
</h2>
{{/if}}
<!-- Extend - End Extend Code -->
The resulting code changes should look similar to the screenshot below:
- In the same file, find the block that starts with
{{#if options}}
and paste the snippet below:
<!-- Extend - Render item info -->
{{#if type '==' 'Custom'}}
<div id="extend-plan-item" data-extend-itemid={{id}}></div>
{{/if}}
<!-- Extend - End Extend Code -->
<!-- Extend - Adds Cart Offer -->
<div
id="extend-cart-offer"
data-extend-item-id="{{id}}"
data-extend-sku="{{sku}}"
data-extend-quantity="{{quantity}}"
></div>
<!-- Extend - End Extend Code -->
Similarly, these code changes should result
Verify
You should now see Extend Warranties you add to the cart appear neatly formatted and contain information regarding the product they're covering along with not being clickable. The Extend warranty quantities should also always match the product they're covering quantity. If you increment the product by 1, the Extend warranty should also increment by 1 automatically.
Way to go! If you see the Extend Warranty includes an Icon and information about the product it's covering and is NOT clickable, you're ready for the next step if you have a drop down cart: Styling Drop down cart
If you do not have a drop down cart, skip to this step: Setting up Extend Analytics & After market support
If you run into any issues during this integration process or have questions please reach out to our team through your Merchant Portal.
Updated 12 months ago