UNPKG

sajari-website

Version:

Website extensions for the Sajari API. Automatically index site content, add user profiles, render search and recommendations, etc.

295 lines (271 loc) 5.77 kB
/* * profile.js - Handles Sajari profile information */ var cookie = require("./utils/cookie"); var encoder = require("./utils/encode"); var unique = require("./utils/unique"); var enc = new encoder(); var isArray = require('sajari/src/js/utils/isArray.js'); var opts = { cname: 'sjID', pname: 'sjPR', ename: 'sjPE', sname: 'sjSE', clicked: 'sjCL', expires: 365, // days maxStrings: 10, // max weighted profile strings to keep maxURLs: 10, // maximum number of url clicks to track weight: 0.05, // default contextual profile weight session: false, // if true, profiles are session based and not stored beyond domain: window.location.hostname.toLowerCase().replace(/^www(.)/, '') }; /** * Profile constructor */ function profile(options) { options = options || {}; for (var o in options) { this[o] = options[o]; } if (options.data === undefined) { this.data = { meta: {}, weighted: [] }; } if (this.data.meta === undefined) { this.data.meta = {}; } if (this.data.weighted === undefined) { this.data.weighted = []; } this.gaId = getGAID(); if (this.visitorId === undefined) { this.visitorId = cookie.get(opts.cname); if (this.visitorId === undefined) { this.visitorId = new Date().getTime() + '.' + Math.floor(Math.random() * 1000000); } } this.sequence = getPageSequence(); this.load(); } profile.prototype = { /** * Load profile meta data */ load: function() { // MIGRATE OLD - REMOVE var p = getLegacySession(opts.pname); if (p) { this.data.meta = p; this.save(); } // END MIGRATE OLD var e; if (opts.session) { e = getSession(opts.ename); if (e) { this.data = e; } return; } e = getLocal(opts.ename); if (e) { this.data = e; } }, /** * Save profile meta data */ save: function() { if (opts.session) { setSession(opts.ename, this.data); return; } setLocal(opts.ename, this.data); }, /** * Set a config option post creation */ option: function(option, value) { if (option && value) { opts[option] = value; } }, /** * Set profile meta data */ set: function(text, meta) { if (meta) { for (var k in meta) { this.data.meta[k] = meta[k]; } this.save(); } if (text) { this.data.weighted.push(text); this.data.weighted = unique(this.data.weighted); if (this.data.weighted.length > this.maxStrings) { this.data.weighted.shift(); } this.save(); } }, /** * Get profile meta data */ get: function() { return this.data; }, /** * If a user clicks a recommended URL, we store that to not show it again in the near future */ addClickedUrl: function(url) { var u = url.split("?"); // TODO: Might be a problem for sites using query params for real stuff var arr = getSession(opts.clicked); if (!arr) { arr = []; } for (var i = 0; i < arr.length; i++) { if (arr[i] === u[0]) { return; } } arr.push(u[0]); if (arr.length > this.maxURLs) { arr.shift(); } setSession(opts.clicked, arr); }, /** * Get the most recent "num" clicked URL's */ getClickedUrls: function(num) { var arr = getSession(opts.clicked); if (arr) { return arr.slice(Math.max(arr.length - num, 1)); } return []; }, /** * Encode to args */ toArgs: function(data) { if (data === undefined) { data = {}; } for (var key in this.data.meta) { var val = this.data.meta[key]; if (isArray(val)) { val = val.join(';'); } else if (typeof val === 'object') { val = JSON.stringify(val); } data['meta[' + key + ']'] = val; } var n = this.data.weighted.length; for (var i = 0; i < n; i++) { var w = ((i + 1) / (n / 0.05)).toFixed(4); data['q[' + w + ']'] = this.data.weighted[i]; } data.mimetype = 'text/plain+weighted'; return data; }, /** * Sets a hardcoded visitor identifier */ setVisitorId: function(id) { if (id !== undefined) { this.visitorId = id + ''; cookie.set(opts.cname, this.visitorId, { path: '/', expires: opts.expires, domain: opts.domain }); } return this.visitorId; } }; /** * Returns the current visitors Google Analytics ID if it exists */ function getGAID() { var userId = ''; var gaUserCookie = cookie.get("_ga"); if (gaUserCookie !== undefined) { var cookieValues = gaUserCookie.split('.'); if (cookieValues.length > 2) { userId = cookieValues[2]; } } return userId; } /* * Contains the page view sequence in this session */ function getPageSequence() { var s = cookie.get(opts.sname); if (s === undefined) { s = 0; } s++; cookie.set(opts.sname, s, { path: '/', domain: opts.domain }); return s; } /* * Set data in local storage safely if it exists */ function setLocal(name, data) { if (typeof(Storage) !== "undefined") { var e = enc.encode(data); localStorage.setItem(name, e); return true; } } /* * Retrieve data in local storage safely if it exists */ function getLocal(name) { if (typeof(Storage) !== "undefined") { var d = localStorage.getItem(name); if (d) { return enc.decode(d); } } } /* * Set data in session storage safely if it exists */ function setSession(name, data) { if (typeof(Storage) !== "undefined") { var e = enc.encode(data); sessionStorage.setItem(name, e); return true; } } /* * Retrieve data in session storage safely if it exists */ function getSession(name) { if (typeof(Storage) !== "undefined") { var d = sessionStorage.getItem(name); if (d) { return enc.decode(d); } } } /* * Retrieve legacy data in session storage safely if it exists */ function getLegacySession(name) { if (typeof(Storage) !== "undefined") { var d = sessionStorage.getItem(name); if (d) { return JSON.parse(d); } } } module.exports = profile;