<commit_before>import feature from './utils/feature';


//  Google Analytics injection.

(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
window.ga('create', 'UA-97851584-1', 'auto');
window.ga('send', 'pageview');


const verbosity = 1;


/*

https://github.com/puckey/you-move-me/issues/315

✔️ = Done.
L = Covered by hyperlink click tracking.
? = Questionable if possible or worthwhile.
T = T/K.
> = Requires manual invocation of a function.

Homepage
L  No. of users who click ?
>  No. of users who click Enter VR
>  No. of users who click Add Performance
-  No. of users coming from a shared link
>  No. of clicks into heads and orb
>  No. of users who reach end credits

About
?  Time spent on each section of the about page (we did this on the madeby.google website)

Enter VR
✔️  No. of users who see Enter VR error ****** sort of... TO BE CONTINUED
✔️  Time spent watching in VR
✔️  No. of users watching Polyfill
✔️  No. of users watching WebVR

Add Performance | Tutorial
L  No. of users who skip the tutorial
L  No. of users who close the tutorial
L  No. of users who add performance (after tutorial)
?  No. of users who see error (after tutorial)

Add Performance | Record
  No. of rounds recorded per session
  Time spent recording a dance before user submits
  No. of users who submit
  No. of users who record again (can we do this?)

Add Performance | Share
L  No. of shares on FB
L  No. of shares on G+
L  No. of shares on T

VR device detection
.  No. users on mobile WebVR
.  No. users on mobile WebVR Polyfill
✔️  No. users on Vive
✔️  No. users on Oculus
✔️  No. users on Samsung Gear

Outbound links
L  Homepage & About - User clicks on WebVR badge
L  Homepage & About - User clicks on terms
L  Homepage & About - User clicks on privacy
L  About - User clicks source code link
L  About - User clicks on technical case study link
L  About - User clicks on any sublinks from tech section (under technology section)


*/


const analytics = {
  //  Super general event recording. Most stuff gets funneled through this.
  record: (obj) => {
    if (verbosity >= 0.5) console.log('Note:', obj);
    if (window.ga !== undefined && typeof window.ga === 'function') {
      window.ga('send', obj);
      if (verbosity >= 0.5) console.log('Noted.');
    }
  },
  //  This is basically a “bounce” event recording.
  recordOutboundLink: (a) => {
    const url = a.getAttribute('href');
    if (verbosity >= 0.5) console.log('Note:', url);
    if (window.ga !== undefined && typeof window.ga === 'function') {
      window.ga('send', 'event', 'outbound', 'click', url, {
        transport: 'beacon',
        hitCallback: function () {},
        //hitCallback: function(){ document.location = url }
      });
    }
    return true;
  },
  //  -------------------------------------------------- Section Session
  // -------------- *************** check with GA that this records session time automagically!!!!!
  // right now this must be called manually
  //  but can we make a location.href event listener instead? would that make sense??????
  recordSectionChange: (label) => {
    if (verbosity >= 0.5) console.log('Note:', label);
    if (window.ga !== undefined && typeof window.ga === 'function') {
      window.ga('set', {
        page: document.location.href,
        title: label,
      });
      window.ga('send', 'pageview');
    }
  },
  recordInternalLink: (a) => { // ****** HOW IS THIS DIF THAN ABOVE?????????
    // const url = a.getAttribute('href');
    // if (verbosity >= 0.5) console.log('Note:', url);
    // if (window.ga !== undefined && typeof window.ga === 'function') {
    //   window.ga('send', 'event', 'outbound', 'click', url, {
    //     transport: 'beacon',
    //     hitCallback: function () {},
    //     //hitCallback: function(){ document.location = url }
    //   });
    // }
    // return true;
  },


  //  -------------------------------------------------- VR Session: VR entry / exit ATTEMPT
  //  NOTE: These functions must be called manually when
  //  the user clicks or taps to initiate a VR session.
  //  Compare to VR entry / exit SUCCESS (far) below.
  recordVREntryAttempt: () => {
    analytics.record({
      hitType: 'event',
      eventCategory: 'VR Session',
      eventAction: 'VR Entry',
      eventLabel: 'VR entry attempted',
    });
  },
  recordVRExitAttempt: () => {
    analytics.record({
      hitType: 'event',
      eventCategory: 'VR Session',
      eventAction: 'VR Exit',
      eventLabel: 'VR exit attempted',
    });
  },
  //  -------------------------------------------------- VR Session: Orb select
  orbSelects: 0,
  recordOrbSelect: () => {
    analytics.orbSelects++;
    analytics.record({
      hitType: 'event',
      eventCategory: 'VR Session',
      eventAction: 'Milestones',
      eventLabel: 'Orb select',
      value: analytics.orbSelects,
      nonInteraction: true, // Don’t count this as separate “page.”
    });
  },
  //  -------------------------------------------------- VR Session: Clicks on Heads
  headSelects: 0,
  recordHeadSelect: () => {
    analytics.headSelects++;
    analytics.record({
      hitType: 'event',
      eventCategory: 'VR Session',
      eventAction: 'Milestones',
      eventLabel: 'Head clicks',
      value: analytics.headSelects,
      nonInteraction: true, // Don’t count this as separate “page.”
    });
  },
  //  -------------------------------------------------- VR Session: Made it to credits
  creditViews: 0,
  recordCreditsView: () => {
    analytics.creditViews++;
    analytics.record({
      hitType: 'event',
      eventCategory: 'VR Session',
      eventAction: 'Milestones',
      eventLabel: 'Credits',
      value: analytics.creditViews,
      nonInteraction: true, // Don’t count this as separate “page.”
    });
  },

  mount: () => {
    /*
<commit_msg>Created generic Countables and Timeables.<commit_after>import feature from './utils/feature';


//  Google Analytics injection.

(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
window.ga('create', 'UA-97851584-1', 'auto');
window.ga('send', 'pageview');


//  Custom Analytics
//  https://github.com/puckey/you-move-me/issues/315

const verbosity = 1;


const analytics = {
  //  Super general event recording. Most stuff gets funneled through this.
  record: (obj) => {
    if (verbosity >= 0.5) console.log('Note:', obj);
    if (window.ga !== undefined && typeof window.ga === 'function') {
      window.ga('send', obj);
      if (verbosity >= 0.5) console.log('Noted.');
    }
  },
  //  This is basically a “bounce” event recording.
  recordOutboundLink: (a) => {
    const url = a.getAttribute('href');
    if (verbosity >= 0.5) console.log('Note:', url);
    if (window.ga !== undefined && typeof window.ga === 'function') {
      window.ga('send', 'event', 'outbound', 'click', url, {
        transport: 'beacon',
        hitCallback: function () {},
        //hitCallback: function(){ document.location = url }
      });
    }
    return true;
  },
  //  -------------------------------------------------- Section Session
  // -------------- *************** check with GA that this records session time automagically!!!!!
  // right now this must be called manually
  //  but can we make a location.href event listener instead? would that make sense??????
  recordSectionChange: (label) => {
    if (verbosity >= 0.5) console.log('Note:', label);
    if (window.ga !== undefined && typeof window.ga === 'function') {
      window.ga('set', {
        page: document.location.href,
        title: label,
      });
      window.ga('send', 'pageview');
    }
  },
  recordInternalLink: (a) => { // ****** HOW IS THIS DIF THAN ABOVE?????????
    // const url = a.getAttribute('href');
    // if (verbosity >= 0.5) console.log('Note:', url);
    // if (window.ga !== undefined && typeof window.ga === 'function') {
    //   window.ga('send', 'event', 'outbound', 'click', url, {
    //     transport: 'beacon',
    //     hitCallback: function () {},
    //     //hitCallback: function(){ document.location = url }
    //   });
    // }
    // return true;
  },
  //  -------------------------------------------------- Countables
  countables: [],
  recordCountable: (label) => {
    if (typeof analytics.countables[label] !== 'number') analytics.countables[label] = 0;
    analytics.countables[label]++;
    analytics.record({
      hitType: 'event',
      eventCategory: 'Countables',
      eventAction: label,
      value: analytics.countables[label],
      nonInteraction: true, // Don’t count this as separate “page.”
    });
  },
  //  -------------------------------------------------- Timeables
  timeables: [],
  recordTimeableStart: (label) => {
    analytics.timeables[label] = Date.now();
  },
  recordTimeableStop: (label) => {
    if (analytics.timeables[label] !== undefined) {
      const duration = Date.now() - analytics.timeables[label];
      analytics.record({
        hitType: 'event',
        eventCategory: 'Timeables',
        eventAction: label,
        value: duration / 1000, //  Unit is seconds, accurate to milliseconds.
        nonInteraction: true,   //  Don’t count this as separate “page.”
      });
    }
  },


  //  -------------------------------------------------- VR Session: VR entry / exit ATTEMPT
  //  NOTE: These functions must be called manually when
  //  the user clicks or taps to initiate a VR session.
  //  Compare to VR entry / exit SUCCESS (far) below.
  recordVREntryAttempt: () => {
    analytics.record({
      hitType: 'event',
      eventCategory: 'VR Session',
      eventAction: 'VR Entry',
      eventLabel: 'VR entry attempted',
    });
  },
  recordVRExitAttempt: () => {
    analytics.record({
      hitType: 'event',
      eventCategory: 'VR Session',
      eventAction: 'VR Exit',
      eventLabel: 'VR exit attempted',
    });
  },
  //  -------------------------------------------------- VR Session: Orb select
  orbSelects: 0,
  recordOrbSelect: () => {
    analytics.orbSelects++;
    analytics.record({
      hitType: 'event',
      eventCategory: 'VR Session',
      eventAction: 'Milestones',
      eventLabel: 'Orb select',
      value: analytics.orbSelects,
      nonInteraction: true, // Don’t count this as separate “page.”
    });
  },
  //  -------------------------------------------------- VR Session: Clicks on Heads
  headSelects: 0,
  recordHeadSelect: () => {
    analytics.headSelects++;
    analytics.record({
      hitType: 'event',
      eventCategory: 'VR Session',
      eventAction: 'Milestones',
      eventLabel: 'Head clicks',
      value: analytics.headSelects,
      nonInteraction: true, // Don’t count this as separate “page.”
    });
  },
  //  -------------------------------------------------- VR Session: Made it to credits
  creditViews: 0,
  recordCreditsView: () => {
    analytics.creditViews++;
    analytics.record({
      hitType: 'event',
      eventCategory: 'VR Session',
      eventAction: 'Milestones',
      eventLabel: 'Credits',
      value: analytics.creditViews,
      nonInteraction: true, // Don’t count this as separate “page.”
    });
  },


  mount: () => {
    /*

{'fraction_non_alphanumeric': 0.20329387545033453, 'fraction_numerical': 0.005404014410705095, 'mean_word_length': 2.3263908701854494, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 41, 'https://': 4, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3661133', 'n_tokens_mistral': 3557, 'n_tokens_neox': 3487, 'n_words': 1016}