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.

605 lines (509 loc) 16.6 kB
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.lastCampaign = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ '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 })); } } },{"cookie":2,"deepmerge":3,"querystring":6}],2:[function(require,module,exports){ /*! * cookie * Copyright(c) 2012-2014 Roman Shtylman * Copyright(c) 2015 Douglas Christopher Wilson * MIT Licensed */ /** * Module exports. * @public */ exports.parse = parse; exports.serialize = serialize; /** * Module variables. * @private */ var decode = decodeURIComponent; var encode = encodeURIComponent; var pairSplitRegExp = /; */; /** * RegExp to match field-content in RFC 7230 sec 3.2 * * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] * field-vchar = VCHAR / obs-text * obs-text = %x80-FF */ var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/; /** * Parse a cookie header. * * Parse the given cookie header string into an object * The object has the various cookies as keys(names) => values * * @param {string} str * @param {object} [options] * @return {object} * @public */ function parse(str, options) { if (typeof str !== 'string') { throw new TypeError('argument str must be a string'); } var obj = {} var opt = options || {}; var pairs = str.split(pairSplitRegExp); var dec = opt.decode || decode; pairs.forEach(function(pair) { var eq_idx = pair.indexOf('=') // skip things that don't look like key=value if (eq_idx < 0) { return; } var key = pair.substr(0, eq_idx).trim() var val = pair.substr(++eq_idx, pair.length).trim(); // quoted values if ('"' == val[0]) { val = val.slice(1, -1); } // only assign once if (undefined == obj[key]) { obj[key] = tryDecode(val, dec); } }); return obj; } /** * Serialize data into a cookie header. * * Serialize the a name value pair into a cookie string suitable for * http headers. An optional options object specified cookie parameters. * * serialize('foo', 'bar', { httpOnly: true }) * => "foo=bar; httpOnly" * * @param {string} name * @param {string} val * @param {object} [options] * @return {string} * @public */ function serialize(name, val, options) { var opt = options || {}; var enc = opt.encode || encode; if (!fieldContentRegExp.test(name)) { throw new TypeError('argument name is invalid'); } var value = enc(val); if (value && !fieldContentRegExp.test(value)) { throw new TypeError('argument val is invalid'); } var pairs = [name + '=' + value]; if (null != opt.maxAge) { var maxAge = opt.maxAge - 0; if (isNaN(maxAge)) throw new Error('maxAge should be a Number'); pairs.push('Max-Age=' + Math.floor(maxAge)); } if (opt.domain) { if (!fieldContentRegExp.test(opt.domain)) { throw new TypeError('option domain is invalid'); } pairs.push('Domain=' + opt.domain); } if (opt.path) { if (!fieldContentRegExp.test(opt.path)) { throw new TypeError('option path is invalid'); } pairs.push('Path=' + opt.path); } if (opt.expires) pairs.push('Expires=' + opt.expires.toUTCString()); if (opt.httpOnly) pairs.push('HttpOnly'); if (opt.secure) pairs.push('Secure'); if (opt.firstPartyOnly) pairs.push('First-Party-Only'); return pairs.join('; '); } /** * Try decoding a string using a decoding function. * * @param {string} str * @param {function} decode * @private */ function tryDecode(str, decode) { try { return decode(str); } catch (e) { return str; } } },{}],3:[function(require,module,exports){ (function (root, factory) { if (typeof define === 'function' && define.amd) { define(factory); } else if (typeof exports === 'object') { module.exports = factory(); } else { root.deepmerge = factory(); } }(this, function () { return function deepmerge(target, src) { var array = Array.isArray(src); var dst = array && [] || {}; if (array) { target = target || []; dst = dst.concat(target); src.forEach(function(e, i) { if (typeof dst[i] === 'undefined') { dst[i] = e; } else if (typeof e === 'object') { dst[i] = deepmerge(target[i], e); } else { if (target.indexOf(e) === -1) { dst.push(e); } } }); } else { if (target && typeof target === 'object') { Object.keys(target).forEach(function (key) { dst[key] = target[key]; }) } Object.keys(src).forEach(function (key) { if (typeof src[key] !== 'object' || !src[key]) { dst[key] = src[key]; } else { if (!target[key]) { dst[key] = src[key]; } else { dst[key] = deepmerge(target[key], src[key]); } } }); } return dst; } })); },{}],4:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; // If obj.hasOwnProperty has been overridden, then calling // obj.hasOwnProperty(prop) will break. // See: https://github.com/joyent/node/issues/1707 function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } module.exports = function(qs, sep, eq, options) { sep = sep || '&'; eq = eq || '='; var obj = {}; if (typeof qs !== 'string' || qs.length === 0) { return obj; } var regexp = /\+/g; qs = qs.split(sep); var maxKeys = 1000; if (options && typeof options.maxKeys === 'number') { maxKeys = options.maxKeys; } var len = qs.length; // maxKeys <= 0 means that we should not limit keys count if (maxKeys > 0 && len > maxKeys) { len = maxKeys; } for (var i = 0; i < len; ++i) { var x = qs[i].replace(regexp, '%20'), idx = x.indexOf(eq), kstr, vstr, k, v; if (idx >= 0) { kstr = x.substr(0, idx); vstr = x.substr(idx + 1); } else { kstr = x; vstr = ''; } k = decodeURIComponent(kstr); v = decodeURIComponent(vstr); if (!hasOwnProperty(obj, k)) { obj[k] = v; } else if (isArray(obj[k])) { obj[k].push(v); } else { obj[k] = [obj[k], v]; } } return obj; }; var isArray = Array.isArray || function (xs) { return Object.prototype.toString.call(xs) === '[object Array]'; }; },{}],5:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; var stringifyPrimitive = function(v) { switch (typeof v) { case 'string': return v; case 'boolean': return v ? 'true' : 'false'; case 'number': return isFinite(v) ? v : ''; default: return ''; } }; module.exports = function(obj, sep, eq, name) { sep = sep || '&'; eq = eq || '='; if (obj === null) { obj = undefined; } if (typeof obj === 'object') { return map(objectKeys(obj), function(k) { var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; if (isArray(obj[k])) { return map(obj[k], function(v) { return ks + encodeURIComponent(stringifyPrimitive(v)); }).join(sep); } else { return ks + encodeURIComponent(stringifyPrimitive(obj[k])); } }).join(sep); } if (!name) return ''; return encodeURIComponent(stringifyPrimitive(name)) + eq + encodeURIComponent(stringifyPrimitive(obj)); }; var isArray = Array.isArray || function (xs) { return Object.prototype.toString.call(xs) === '[object Array]'; }; function map (xs, f) { if (xs.map) return xs.map(f); var res = []; for (var i = 0; i < xs.length; i++) { res.push(f(xs[i], i)); } return res; } var objectKeys = Object.keys || function (obj) { var res = []; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key); } return res; }; },{}],6:[function(require,module,exports){ 'use strict'; exports.decode = exports.parse = require('./decode'); exports.encode = exports.stringify = require('./encode'); },{"./decode":4,"./encode":5}]},{},[1])(1) });