Checkout Extension
Checkout Extension
Section titled “Checkout Extension”If you use Shopify Plus and have not yet updated to the new “extensible checkout” system, you can use the “Edit Code” feature in your Shopify theme to add the Quikly checkout snippet.
- Create a new snippet called ‘quikly.liquid’. Make sure you replace ##REPLACE_WITH_BRAND_ID## with your config key provided by Quikly. You can find the full source of this file below.
- Edit the checkout.liquid file, and add
{% render 'quikly' %}
to include the new snippet. Typically you will want to place this directly above the{{ content_for_layout }}
tag
<main class="main__content" role="main"> {% render 'quikly' %} {{ content_for_layout }}</main>
Here is the contents of snippets/quikly.liquid.
<script type="application/javascript"> (function (d) { if (d.getElementById('quikly-embed-js')) { return; } s = d.createElement("script"); s.id = 'quikly-embed-js'; s.src = 'https://pixel.quikly.com/embed/js'; s.async = true; f = d.scripts[0]; f.parentNode.insertBefore(s, f); })(document); window.qData || (window.qData = function() { (window.qDataLayer = window.qDataLayer || []).push(arguments); }); qData('config', '##REPLACE_WITH_YOUR_BRAND_KEY##'); try { var qCheckoutTemplate = '{% if checkout %}checkout{% else %}{{ template }}{% endif %}'; if (window.Shopify && window.Shopify.Checkout) { if (window.Shopify.Checkout.step === 'thank_you') { qCheckoutTemplate = 'thank_you'; } else if (Shopify.Checkout.isOrderStatusPage) { qCheckoutTemplate = 'order_status'; } } qData('ui', { placements: 'auto', platformData: { platform: 'shopify', template: qCheckoutTemplate, } }); } catch (error) { console.log(error); }
var quiklyAppExtension = (function() { const Q_SCOPE = 'q_scope'; function getLastClickedScope(scopes) { const scopesArray = []; Object.keys(scopes).forEach((key) => { scopesArray.push({ [Q_SCOPE]: key, clicked: scopes[key].clicked }); });
// Sort descending by click time scopesArray.sort((a, b) => { return b.clicked - a.clicked; });
// First in array has highest click UNIX timestamp === last to be clicked return scopesArray[0][Q_SCOPE]; }
function getCookieValue(key) { // if cookie is not set do not try to split const cookie = document.cookie .split("; ") .find((row) => row.startsWith(key)); if (!cookie) { return; }
return cookie.split("=")[1]; }
function notifyQuikly(cart) { const evt = new CustomEvent("quikly:cart", { detail: { cart, }, });
window.dispatchEvent(evt); }
function getBaseUrl(key, defaultUrl) { if (window.QuiklyRoutes && window.QuiklyRoutes[key]) { return window.QuiklyRoutes[key] + ".js"; }
if (window.Shopify && window.Shopify.routes && window.Shopify.routes.root) { return window.Shopify.routes.root + defaultUrl; }
return defaultUrl; }
function cartUrl() { return getBaseUrl("cart_url", "{{ routes.cart_url | default: 'cart' }}.js"); }
function cartUpdateUrl() { return getBaseUrl("cart_update_url", "{{ routes.cart_update_url | default: 'cart/update' }}.js"); }
async function fetchCart() { try { const response = await fetch(cartUrl()); return response.json(); } catch (error) { console.error("Error fetching cart:", error); throw error; } }
function getCookieScope() { const cookieScope = getCookieValue(Q_SCOPE); if (cookieScope) { const decodedQscopeCookieValue = decodeURIComponent(cookieScope); const parsedQscope = JSON.parse(decodedQscopeCookieValue); const qscope = getLastClickedScope(parsedQscope); return qscope; } }
function fetchConfig(type = "json") { return { method: "POST", headers: { "Content-Type": "application/json", Accept: `application/${type}`, }, }; }
async function synchronizeCart() { let updateCart = false; let cart; let attributes;
try { cart = await fetchCart(); notifyQuikly(cart); attributes = cart["attributes"] || {};
const cookieQScope = getCookieScope(); if (cookieQScope && attributes[Q_SCOPE] !== cookieQScope) { attributes[Q_SCOPE] = cookieQScope; updateCart = true; }
const receiptTokens = getCookieValue("quikly-order-receipt-tokens"); if (receiptTokens && attributes["q_tokens"] !== receiptTokens) { attributes["q_tokens"] = receiptTokens; updateCart = true; }
if (updateCart) { const body = JSON.stringify({ attributes });
const fetchResult = await fetch(cartUpdateUrl(), { ...fetchConfig(), ...{ body }, });
if (!fetchResult.ok) { throw new Error( `Cart update failed with status ${fetchResult.status}` ); }
return fetchResult.json(); } } catch (error) { console.error("Error updating cart:", error); } }
async function applyDiscount(code) { const res = await fetch(`/checkout?discount=${code}`); return res.text(); }
synchronizeCart();
return { fetchCart: fetchCart, applyDiscount: applyDiscount, } })();
{% if checkout %} (function($) { $(document).on("page:change", function() { quiklyAppExtension.fetchCart(); }); })(Checkout.$);{% endif %}</script>