Skip to content

Instantly share code, notes, and snippets.

@stewartknapman
Last active March 7, 2019 23:49
Show Gist options
  • Save stewartknapman/f602c73c7c00b6f6e07c2a51e07abaa2 to your computer and use it in GitHub Desktop.
Save stewartknapman/f602c73c7c00b6f6e07c2a51e07abaa2 to your computer and use it in GitHub Desktop.
Shopify: Track the last viewed collection and update any continue shopping links.

ContinueShopping

Track the last collection by storing or updating a cookie on every collection page visit. If it comes across a continue shopping link then it updates that link to point back to that last collection.

Add the attribute data-continue-shopping-link to any link you want to act as a continue shopping link.

Requires the current template to be passed to it from liquid:

<script>
  var theme.template = {{ template | json }};
</script>
(function () {
if (!document.querySelector) return;
/*\
|*|
|*| :: cookies.js ::
|*|
|*| A complete cookies reader/writer framework with full unicode support.
|*|
|*| Revision #3 - July 13th, 2017
|*|
|*| https://developer.mozilla.org/en-US/docs/Web/API/document.cookie
|*| https://developer.mozilla.org/User:fusionchess
|*| https://github.com/madmurphy/cookies.js
|*|
|*| This framework is released under the GNU Public License, version 3 or later.
|*| http://www.gnu.org/licenses/gpl-3.0-standalone.html
|*|
|*| Syntaxes:
|*|
|*| * docCookies.setItem(name, value[, end[, path[, domain[, secure]]]])
|*| * docCookies.getItem(name)
|*| * docCookies.removeItem(name[, path[, domain]])
|*| * docCookies.hasItem(name)
|*| * docCookies.keys()
|*|
\*/
var docCookies = {
getItem: function (sKey) {
if (!sKey) { return null; }
return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
},
setItem: function (sKey, sValue, vEnd, sPath, sDomain, bSecure) {
if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; }
var sExpires = "";
if (vEnd) {
switch (vEnd.constructor) {
case Number:
// sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd;
/*
Note: Despite officially defined in RFC 6265, the use of `max-age` is not compatible with any
version of Internet Explorer, Edge and some mobile browsers. Therefore passing a number to
the end parameter might not work as expected. A possible solution might be to convert the the
relative time to an absolute time. For instance, replacing the previous line with:
*/
sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; expires=" + (new Date(vEnd * 1e3 + Date.now())).toUTCString();
break;
case String:
sExpires = "; expires=" + vEnd;
break;
case Date:
sExpires = "; expires=" + vEnd.toUTCString();
break;
}
}
document.cookie = encodeURIComponent(sKey) + "=" + encodeURIComponent(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : "");
return true;
},
removeItem: function (sKey, sPath, sDomain) {
if (!this.hasItem(sKey)) { return false; }
document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "");
return true;
},
hasItem: function (sKey) {
if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; }
return (new RegExp("(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
},
keys: function () {
var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/);
for (var nLen = aKeys.length, nIdx = 0; nIdx < nLen; nIdx++) { aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]); }
return aKeys;
}
};
/*
Run code as soon as the page is ready
*/
var ready = function (callback, ctx) {
if (typeof callback !== 'function') return;
if (document.readyState !== "loading") {
callback.apply(ctx);
} else {
document.addEventListener("DOMContentLoaded", function () {
callback.apply(ctx);
});
}
};
/*
ContinueShopping
Track the last collection by storing or updating a cookie on every collection page visit.
If it comes across a continue shopping link then it updates that link to point back to that last collection.
Add the attribute data-continue-shopping-link to any link you want to act as a continue shopping link.
Requires the current template to be passed to it from liquid:
<script>
var theme.template = {{ template | json }};
</script>
*/
var ContinueShopping = function () {
this.continueShoppingLinkSelector = '[data-continue-shopping-link]';
this.cookieName = 'lastCollection';
this.cookieDuration = 2628000; // Set for 1 month
this.checkPage();
};
ContinueShopping.prototype.checkPage = function () {
if (this._templateContains('collection')) {
this._storeCollection();
}
this.updateCartButton();
};
ContinueShopping.prototype.updateCartButton = function () {
var continueShoppingLinks = document.querySelectorAll(this.continueShoppingLinkSelector);
if (continueShoppingLinks.length && docCookies.hasItem(this.cookieName)) {
var collectionHref = docCookies.getItem(this.cookieName);
for (var i = 0; i < continueShoppingLinks.length; i++) {
continueShoppingLinks[i].href = collectionHref;
}
}
};
// Private
ContinueShopping.prototype._templateContains = function (str) {
if (theme.template) {
return theme.template.indexOf(str) >= 0;
} else {
return false;
}
}
ContinueShopping.prototype._storeCollection = function () {
docCookies.setItem(this.cookieName, location.pathname, this.cookieDuration, '/');
};
ready(function () {
window.continueShopping = new ContinueShopping();
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment