UNPKG

last-campaign

Version:

Saves campaign query string parameters into a session cookie so they can be retrieved and passed to your marketing automation system when needed.

209 lines (178 loc) 5.34 kB
'use strict'; var querystring = require('querystring'); var cookie = require('cookie'); var merge = require('deepmerge'); /** * Module exports. * @public */ module.exports = saveLastCampaign; /** * saveLastCampaign * * Saves campaign query string parameters into a session cookie so they can be * retrieved and passed to your marketing automation system when needed. * * @param {object} [opts] Options object. * @param {string} [opts.prefix] Cookie name prefix. * @param {array} [opts.params] Default parameters. * @param {array} [opts.extra] Extra parameters. * @public */ function saveLastCampaign(opts) { var options = { defaults: true, prefix: '', params: [ 'utm_campaign', 'utm_source', 'utm_medium', 'utm_term', 'utm_content' ], data: {}, path: '/', domain: null, timeout: 30 }; var pageQueryString = getQueryString(); var data = {}; var cookieOptions = {}; var now = new Date(); var expires; // Remove default parameters if necessary if (typeof opts === 'object') { if (typeof opts.defaults !== 'undefined' && opts.defaults === false) { options.params = []; } } // Merge opts onto options if (arguments.length && typeof opts === 'object') { options = merge(options, opts); } var dataKeys = Object.keys(options.data); // Set default cookie options cookieOptions = { domain: options.domain, path: options.path }; // Set cookie expiration and advance expiration for existing cookies if (options.timeout) { expires = new Date(now.setMinutes(now.getMinutes() + options.timeout)); // querystring param cookies options.params.forEach(function (key) { updateExpiration(options.prefix + key, expires, cookieOptions); }); // data object cookies if (dataKeys.length !== 0) { dataKeys.forEach(function (key) { updateExpiration(options.prefix + key, expires, cookieOptions); }); } } // Parse the query string if (pageQueryString.length !== 0) { data = querystring.parse(pageQueryString); var removed = false; // Create the cookies options.params.forEach(function (key) { if (data[key]) { // param found in querystring so remove all necessary existing cookies first if (!removed) { removeCookies(options, cookieOptions); removed = true; } // Merge expires in to prevent the following error: // Uncaught TypeError: opt.expires.toUTCString is not a function setCookie(options.prefix + key, data[key], merge(cookieOptions, { expires: expires })); } }); } // Save the data object if (dataKeys.length !== 0) { dataKeys.forEach(function (key) { // Skip undefined, null, or empty values if (typeof options.data[key] === 'undefined' || options.data[key] === null || options.data[key] === '') { return; } // Create the cookie if it doesn't exist if (!getCookie(key)) { setCookie(options.prefix + key, options.data[key], merge(cookieOptions, { expires: expires })); } }); } } /** * Remove all cookies matching options.params * @param {Object} options * @private */ function removeCookies(options, cookieOptions) { options.params.forEach(function (key) { document.cookie = cookie.serialize(options.prefix + key, '', merge(cookieOptions, { expires: new Date('Thu, 01 Jan 1970 00:00:00 GMT') })); }); } /** * Returns the query string without its initial question mark. * * E.g. foo=bar&baz=qux * * @return {string} * @private */ function getQueryString() { return window.location.search.substring(1); } /** * Sets a browser cookie given a valid cookie string. * * E.g. "foo=bar; httpOnly" * * @param {string} name - name of cookie * @param {string} value - value of cookie * @param {object} options - object containing cookie options * @private */ function setCookie(name, value, options) { document.cookie = cookie.serialize(name, value, options); } /** * Returns cookie value * * @param {string} name - name of cookie * @return {string} token * @private */ function getCookie(name) { if (arguments.length === 0 && typeof opts !== 'string') { return; } var match = document.cookie.match('(?:^|; )' + name + '=([^;]+)'); if (match) { return match[1]; } else { return ''; } } /** * Update cookie expiration * * @param {string} name - name of cookie * @param {date} expires - expiration date/time of cookie * @param {object} options - object containing cookie options * @private */ function updateExpiration(name, expires, options) { var existingValue = getCookie(name); if (existingValue) { setCookie(name, existingValue, merge(options, { expires: expires })); } }