Skip to content

Commit

Permalink
Attempt to pass a good user_id to GA
Browse files Browse the repository at this point in the history
Decided to just watch the USER_ANNOUNCEMENT event since this should be called by the pubsub after the user is updated.

This value must be hashed though to avoid leaking user information, so it may limit to browsers supporting `window.crypto`.

@see https://caniuse.com/cryptography

Seems like good coverage as of now, so hopefully safe to use this here without polyfills.
  • Loading branch information
thostetler committed Feb 15, 2024
1 parent 16c0e0b commit 696a8d1
Showing 1 changed file with 56 additions and 25 deletions.
81 changes: 56 additions & 25 deletions src/js/components/navigator.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
/**
/**
* Created by rchyla on 3/10/14.
*/

Expand All @@ -21,22 +21,38 @@ define([
'js/components/transition',
'js/components/transition_catalog',
'analytics',
], function(
], function (
_,
$,
Cache,
GenericModule,
Mixins,
Transition,
TransitionCatalog,
analytics
analytics,
) {
// Document Title Constants
var APP_TITLE = 'NASA/ADS';
var TITLE_SEP = ' - ';

// This function is used to hash the user id before sending it to Analytics
const digestMessage = function (message) {
const crypto = window.crypto || window.msCrypto;
if (!crypto) {
return Promise.reject(new Error('Crypto not available'));
}
// encode as (utf-8) Uint8Array
const msgUi8 = new TextEncoder().encode(message);

// hash the message
return crypto.subtle.digest('SHA-256', msgUi8).then((hashBuffer) => {
const hashArray = Array.from(new Uint8Array(hashBuffer));
return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
});
};

var Navigator = GenericModule.extend({
initialize: function(options) {
initialize: function (options) {
options = options || {};
this.router = options.router;
this.catalog = new TransitionCatalog(); // catalog of nagivation points (later we can build FST)
Expand All @@ -48,39 +64,54 @@ define([
* @param beehive - the full access instance; we excpect PubSub to be
* present
*/
activate: function(beehive) {
activate: function (beehive) {
this.setBeeHive(beehive);
this.storage = beehive.getObject('AppStorage');
var pubsub = this.getPubSub();
pubsub.subscribe(pubsub.NAVIGATE, _.bind(this.navigate, this));
pubsub.subscribe(pubsub.CUSTOM_EVENT, _.bind(this._onCustomEvent, this));
pubsub.subscribe(
pubsub.USER_ANNOUNCEMENT,
_.bind(this._onUserAnnouncement, this),
);
},

_onUserAnnouncement: function (ev, data) {
if (ev === 'user_signed_in' && typeof data === 'string') {
// the user is signed in, we can associate the user with the session
digestMessage(data).then((userIdHash) => {
analytics('send', 'user_update', {
user_id: userIdHash,
});
});
}
},

_onCustomEvent: function(ev, data) {
_onCustomEvent: function (ev, data) {
if (ev === 'update-document-title') {
this._updateDocumentTitle(data);
}
},

_cleanRoute: function(route) {
_cleanRoute: function (route) {
const r = route.match(/[#\/]?([^\/]*)\//);
if (r && r.length > 1) {
return '/' + r[1];
}
return route;
},

_setPageAndEmitEvent: _.debounce(function(route, pageName) {
analytics('set', 'page', this._cleanRoute(route));
analytics('send', 'pageview', {
dimension1: pageName,
_setPageAndEmitEvent: _.debounce(function (route, pageName) {
analytics('send', 'virtual_page_view', {
page_name: pageName,
clean_route: this._cleanRoute(route),
});
}, 300),

/**
* Responds to PubSubEvents.NAVIGATE signal
*/
navigate: function(ev, arg1, arg2) {
navigate: function (ev, arg1, arg2) {
var defer = $.Deferred();
var self = this;

Expand All @@ -101,7 +132,7 @@ define([
return defer.resolve().promise();
}

var afterNavigation = _.bind(function() {
var afterNavigation = _.bind(function () {
// router can communicate directly with navigator to replace url
var replace = !!(transition.replace || (arg1 && arg1.replace));

Expand All @@ -116,8 +147,8 @@ define([

// clear any metadata added to head on the previous page
$('head')
.find('meta[data-highwire]')
.remove();
.find('meta[data-highwire]')
.remove();
this._updateDocumentTitle(transition.title);
defer.resolve();
}, this);
Expand All @@ -135,10 +166,10 @@ define([
return defer.promise();
},

_updateDocumentTitle: function(title) {
_updateDocumentTitle: function (title) {
if (_.isUndefined(title) || title === false) return;
var currTitle = this.storage.getDocumentTitle();
var setDocTitle = _.bind(function(t) {
var setDocTitle = _.bind(function (t) {
document.title = t === '' ? APP_TITLE : t + TITLE_SEP + APP_TITLE;
this.storage.setDocumentTitle(t);
}, this);
Expand All @@ -149,16 +180,16 @@ define([
}
},

handleMissingTransition: function(transition) {
handleMissingTransition: function (transition) {
console.error(
"Cannot handle 'navigate' event: " + JSON.stringify(arguments)
"Cannot handle 'navigate' event: " + JSON.stringify(arguments),
);
var ps = this.getPubSub();
ps.publish(ps.BIG_FIRE, 'navigation-error', arguments);
if (this.catalog.get('404')) ps.publish(ps.NAVIGATE, '404');
},

handleTransitionError: function(transition, error, args) {
handleTransitionError: function (transition, error, args) {
console.error('Error while executing transition', transition, args);
console.error(error.stack);
var ps = this.getPubSub();
Expand All @@ -170,7 +201,7 @@ define([
* Sets the transition inside the catalog; you can pass simplified
* list of options or the Transition instance
*/
set: function() {
set: function () {
if (arguments.length == 1) {
if (arguments[1] instanceof Transition) {
return this.catalog.add(arguments[1]);
Expand All @@ -182,7 +213,7 @@ define([
return this.catalog.add(
new Transition(endpoint, {
execute: arguments[1],
})
}),
);
}
if (_.isObject(arguments[1]) && arguments[1].execute) {
Expand All @@ -191,18 +222,18 @@ define([

throw new Error(
'Himmm, I dont know how to create a catalog rule with this input:',
arguments
arguments,
);
} else {
// var args = array.slice.call(arguments, 1);
throw new Error(
'Himmm, I dont know how to create a catalog rule with this input:',
arguments
arguments,
);
}
},

get: function(endpoint) {
get: function (endpoint) {
return this.catalog.get(endpoint);
},
});
Expand Down

0 comments on commit 696a8d1

Please sign in to comment.