PageSourceSearch

https://www.guitargate.com/modules/custom/gg_experiments/js/experiment-funnel.js?tlvh25

js guitargate.com collected 2026-09-25 02:34:15 UTC 4,101 bytes, 108 lines download raw bytes

1/**
2 * @file
3 * Experiment funnel event tracking.
4 *
5 * Fires non-fatal beacons for funnel steps when experiment cookies are present.
6 * All tracking is fire-and-forget, deduped per session via sessionStorage.
7 */
8(function (Drupal, drupalSettings) {
9  'use strict';
10
11  var abConfig = drupalSettings.abExperiment || {};
12  var IMPRESSIONS_URL = abConfig.impressionsUrl;
13  var API_KEY = abConfig.apiKey;
14
15  if (!IMPRESSIONS_URL || !API_KEY) return;
16
17  function getCookie(name) {
18    try {
19      var cookies = document.cookie.split(';');
20      for (var i = 0; i < cookies.length; i++) {
21        var cookie = cookies[i].replace(/^\s+/, '');
22        if (cookie.indexOf(name + '=') === 0) {
23          return decodeURIComponent(cookie.substring(name.length + 1));
24        }
25      }
26    } catch (e) {}
27    return '';
28  }
29
30  function fireFunnelEvent(type) {
31    try {
32      var experimentId = getCookie('gg_experiment_id');
33      var variantId = getCookie('gg_variant');
34      var visitorId = getCookie('gg_visitor_id');
35      if (!experimentId || !variantId || !visitorId) return;
36
37      var dedupeKey = 'gg_funnel_' + type;
38      if (sessionStorage.getItem(dedupeKey)) return;
39      sessionStorage.setItem(dedupeKey, '1');
40
41      var payload = {
42        experimentId: experimentId,
43        variantId: variantId,
44        visitorId: visitorId,
45        type: type
46      };
47
48      // Piggyback the authenticated user's email on the beacon so the
49      // trackImpressions Lambda can persist an email → variant mapping.
50      // This is the durable fallback path: Drupal's ConversionTrackingService
51      // hashes the order email at subscription time and looks up this mapping.
52      // Deduped per experiment per session to avoid hammering Lambda.
53      var userMail = drupalSettings.user && drupalSettings.user.mail;
54      if (userMail) {
55        var attrKey = 'gg_attr_sent_' + experimentId;
56        if (!sessionStorage.getItem(attrKey)) {
57          payload.email = userMail;
58          // Tell the Lambda whether this user is already a paying member. If
59          // they are, the beacon's funnel event must NOT create a first-touch
60          // attribution row — they already converted, so it cannot be the
61          // first touch of a FUTURE purchase (gg-f9ij). The counter still
62          // records the raw event; only the attribution write is suppressed.
63          payload.alreadyMember = !!(drupalSettings.user && drupalSettings.user.isMember);
64          // Whether the user already OWNS a Teleport (the top tier). gg-s5e3j:
65          // the Lambda gates ONLY top-tier members out of attribution; a 2.0
66          // subscriber (alreadyMember=true but isTeleportMember=false) IS a
67          // valid first-touch for a FUTURE Teleport upgrade, tagged
68          // source='upgrade_candidate'. Forwarding this distinguishes the two.
69          payload.isTeleportMember = !!(drupalSettings.user && drupalSettings.user.isTeleportMember);
70          try { sessionStorage.setItem(attrKey, '1'); } catch (e) {}
71        }
72      }
73
74      fetch(IMPRESSIONS_URL, {
75        method: 'POST',
76        headers: { 'Content-Type': 'application/json', 'x-api-key': API_KEY },
77        body: JSON.stringify(payload)
78      }).catch(function () {});
79    } catch (e) {}
80  }
81
82  // Bail early if no experiment cookie.
83  if (!getCookie('gg_experiment_id')) return;
84
85  var funnel = drupalSettings.ggExperimentFunnel || {};
86
87  if (funnel.justRegistered) {
88    fireFunnelEvent('registration');
89  }
90
91  if (funnel.lessonView) {
92    fireFunnelEvent('course_start');
93  }
94
95  // Detect lesson_complete flag via AJAX command interception.
96  if (Drupal.AjaxCommands && Drupal.AjaxCommands.prototype) {
97    var originalFlash = Drupal.AjaxCommands.prototype.actionLinkFlash;
98    Drupal.AjaxCommands.prototype.actionLinkFlash = function (ajax, response, status) {
99      if (response.selector && response.selector.indexOf('js-flag-lesson-complete') !== -1) {
100        fireFunnelEvent('course_complete');
101      }
102      if (originalFlash) {
103        originalFlash.call(this, ajax, response, status);
104      }
105    };
106  }
107
108})(Drupal, drupalSettings);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.