Paste Search Dynamic
Recent pastes
jester.js
  1. define('core/analytics/jester',[
  2.     'jquery',
  3.     'underscore',
  4.     'backbone',
  5.  
  6.     'core/analytics/identity',
  7.     'core/config/urls',
  8. ], function (
  9.     $,
  10.     _,
  11.     Backbone,
  12.  
  13.     identity,
  14.     urls
  15. ) {
  16.     'use strict';
  17.  
  18.     /*
  19.         Jester is an ActivityStreams logger for Disqus.
  20.  
  21.         # About Product, Zone, Section, Area:
  22.  
  23.         Yeah, you are probably confused about what these descriptors mean. We are mostly confused, too.
  24.         So, to help out, here is a comprehensive guide:
  25.  
  26.             Product
  27.                 A product is a suite of one or many applications that fall underneath an analytics
  28.                 'umbrella'. These are currently only 'embed' and 'home'.
  29.  
  30.             Zone
  31.                 A zone represents the product application that the user is currently interacting with.
  32.                 These are currently 'thread', 'notifications', 'profile', 'onboard', and 'community'.
  33.  
  34.             Section
  35.                 Section is the "route" that the application is currently displaying. This is analogous
  36.                 to a Backbone.Router method. It must uniquely represent the *visual state* of the application
  37.                 at the time of the interaction we are logging. Applications may have only one route, or
  38.                 they may have many routes.
  39.  
  40.             Area
  41.                 An xpath-ish type identifier that describes where in the DOM the logged interaction took place,
  42.                 if any. Some interactions may not have a DOM location, in which case 'n/a' is sent instead.
  43.                 Actual Xpath not really required.
  44.  
  45.         # Serializing Product, Zone, Section, Area:
  46.  
  47.         When we serialize Product, Zone, Section, or Area as an ActivitySteam object, we use a specific format
  48.         that allows for proper analytics rollups both between products and between cross product applications:
  49.  
  50.         Products:
  51.             object_type='product'
  52.             object_id=<product name>
  53.  
  54.         Zones:
  55.             object_type='zone'
  56.             object_id=<zone name>
  57.  
  58.         Sections:
  59.             object_type='section'
  60.             object_id=<zone name>/<section name>
  61.  
  62.         Areas:
  63.             object_type='area'
  64.             object_id=<zone name>/<section name>#<area name>
  65.     */
  66.  
  67.     var ActivityClient = Backbone.Model.extend({
  68.         url: urls.jester + '/event.js',
  69.  
  70.         defaults: {
  71.             experiment: 'default',
  72.             variant: 'control',
  73.         },
  74.  
  75.         setHostReferrer: function (url) {
  76.  
  77.             if (!url) {
  78.                 // Indicate no referrer as direct traffic
  79.                 this.set('page_referrer', 'direct');
  80.             } else if (url.indexOf('http') === -1) {
  81.                 // We should only set fully qualified URLs as
  82.                 // the referrer domain.
  83.             } else {
  84.                 // If this the client visited cnn.com from facebook.com/xxxx,
  85.                 // and cnn.com loaded this embed, the page_referrer would
  86.                 // be facebook.com/xxxx.
  87.                 this.set('page_referrer', url);
  88.             }
  89.         },
  90.  
  91.         decoratePayload: function (payload) {
  92.  
  93.             // The default category for all our events
  94.             // is 'activity'. Only allow overrides of this
  95.             // during an `emit` call.
  96.             if (!payload.event)
  97.                 payload.event = 'activity';
  98.  
  99.             // Allow payload attributes to override attributes
  100.             // set on the client instance.
  101.             payload = _.extend(this.toJSON(), payload);
  102.  
  103.             _.extend(payload, {
  104.                 imp: identity.impression.impId,
  105.                 prev_imp: identity.impression.prevImp,
  106.             });
  107.  
  108.             // If there is no current application route for this event,
  109.             // we assume it is the 'default' route of the application.
  110.             if (!payload.section)
  111.                 payload.section = 'default';
  112.  
  113.             // If there is no specified event xpath (maybe this event did not
  114.             // originate in the DOM), then we pass Not Available.
  115.             if (!payload.area)
  116.                 payload.area = 'n/a';
  117.  
  118.             // IE8 and IE9 has a stupid limit on the URL length and we cannot
  119.             // use POST method with Jester yet due to CORS issues (again in IE8
  120.             // and IE9) so we simply check total length of the QSA part as
  121.             // mentioned in MS KB article http://support.microsoft.com/kb/q208427
  122.             // and if it is longer than the limit, 2048 chars, we replace it
  123.             // with a more modest, page_referrer_domain
  124.             //
  125.             // NOTE: The final URL is still NOT guaranteed to be < 2048 chars
  126.             var qsaLength = $.param(payload).length;
  127.             if (qsaLength > 2048 && this.has('page_referrer')) {
  128.                 var referrerLink = window.document.createElement('a');
  129.                 referrerLink.href = this.get('page_referrer');
  130.                 var hostname = referrerLink.hostname;
  131.  
  132.                 if (hostname)
  133.                     payload.page_referrer_domain = hostname;
  134.  
  135.                 delete payload.page_referrer;
  136.             }
  137.  
  138.             return payload;
  139.         },
  140.  
  141.         emit: function (payload) {
  142.             // Fire the event to the jester endpoint and return
  143.             // the deferred object
  144.             return $.ajax({
  145.                 url: _.result(this, 'url'),
  146.                 data: this.decoratePayload(payload),
  147.                 dataType: 'script',
  148.  
  149.                 // default is false for 'script' dataType, setting to true
  150.                 // so that "_={timestamp}" isn't appended to this request
  151.                 cache: true,
  152.             });
  153.         },
  154.     });
  155.  
  156.     var logStat = function logStat(name) {
  157.         var beacon = new window.Image();
  158.         beacon.src = urls.jester + '/stat.gif?' + $.param({ event: name });
  159.  
  160.         return beacon;
  161.     };
  162.  
  163.     var telemetry = function telemetry(endpoint, payload) {
  164.         if (_.any(payload, function (val) { return val < 0; }))
  165.             return;  // discard the whole data set if anything looks wrong
  166.  
  167.         // Round all values since statsd expects integers
  168.         _.each(payload, function (val, key) { payload[key] = Math.round(val); });
  169.  
  170.         var beacon = new window.Image();
  171.         beacon.src = urls.jester + '/telemetry/' + endpoint + '.gif?' + $.param(payload);
  172.  
  173.         return beacon;
  174.     };
  175.  
  176.     var client = new ActivityClient();
  177.  
  178.     client.setHostReferrer(window.document.referrer);
  179.  
  180.     return {
  181.         ActivityClient: ActivityClient,
  182.         client: client,
  183.         logStat: logStat,
  184.         telemetry: telemetry,
  185.     };
  186. });
  187.  
  188.  
Parsed in 0.022 seconds