2b7011a74947b7d29548ac9cf619dc4781bde4fb
max
  Fri Mar 3 07:08:27 2023 -0800
sending db as an event on hgTracks page load to ga4, refs #30725

diff --git src/hg/lib/googleAnalytics.c src/hg/lib/googleAnalytics.c
index 6b6d62e..b9503cf 100644
--- src/hg/lib/googleAnalytics.c
+++ src/hg/lib/googleAnalytics.c
@@ -1,125 +1,133 @@
 /* Copyright (C) 2014 The Regents of the University of California 
  * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */
 
 #include "common.h"
 #include "hgConfig.h"
 #include "hPrint.h"
 #include "googleAnalytics.h"
 #include "htmshell.h"
 
 void googleAnalyticsSetGa4Key()
 /* if the google analytics key is a GA4 key, set the variable in htmlshell */
 {
 char *analyticsKey = cfgOption("analyticsKey");
 if (analyticsKey && startsWith("G-", analyticsKey))
     htmlSetGa4Key(analyticsKey);
 }
 
 void googleAnalytics()
 /* check for analytics configuration item and output google hooks if OK */
 {
 static boolean done = FALSE;
 
 if (done)
     return;
 
 done = TRUE;	/*	do not repeat this by mistake	*/
 
 char *analyticsKey = cfgOption("analyticsKey");
 
-// link tracking broke in Firefox once. In case this ever happens again, we can
-// now switch off outlink tracking quickly
-boolean trackClicks = cfgOptionBooleanDefault("analytics.trackClicks", TRUE);
-boolean trackButtons = cfgOptionBooleanDefault("analytics.trackButtons", TRUE);
-
 /*	if config is missing or empty, nothing happens here	*/
 if (isEmpty(analyticsKey))
     return;
 
+char* scriptName = getenv("SCRIPT_NAME");
+if (!scriptName)
+    return;
+char* cgiName = basename(scriptName);
+
 // new GA4 tags start with G- and should be used with the entirely new system called Google Tag Manager,
 // which is a different Javascript, new functions, totally different features.
 if (startsWith("G-", analyticsKey))
     {
     jsInlineF(
         "// Google tag load (gtag.js)\n"
         "   window.dataLayer = window.dataLayer || [];\n"
         "   function gtag(){dataLayer.push(arguments);}\n"
         "   gtag('js', new Date()); gtag('config', '%s');\n"
         "// Google tag load end\n", analyticsKey);
+
+    if (sameWord(cgiName, "hgTracks"))
+        jsInlineF(
+        "  $(document).ready(function() {\n"
+        "          if (gtag) {\n" // When using an Adblocker, the ga object does not exist
+        "              /* send db to ga4 as an event on page load */\n"
+        "              gtag('event', 'hgTracksLoad', {'db': getDb()})\n"
+        "          };\n"
+        "  });");
     return;
     }
 
+// link tracking broke in Firefox once. In case this ever happens again, we can
+// now switch off outlink tracking quickly
+boolean trackClicks = cfgOptionBooleanDefault("analytics.trackClicks", TRUE);
+boolean trackButtons = cfgOptionBooleanDefault("analytics.trackButtons", TRUE);
+
 // replace analytics.js below with analytics_debug.js to activate ga debugging
 // It will log all events and all data that is sent to the javascript console, very handy
 jsInlineF(
 "  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n"
 "  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n"
 "  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n"
 "  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');\n"
 "  ga('create', '%s', 'auto');\n"
 "  ga('require', 'displayfeatures');\n"
 "  ga('set', 'transport', 'beacon');\n" // default to beacons. Old browser cannot use them, so ga will use an alternative.
 "  ga('send', 'pageview');\n"
 "\n"
 , analyticsKey);
 
-// to reduce the risk of breaking existing click handlers, only track links on hgc and hgTracks pages
-char* scriptName = getenv("SCRIPT_NAME");
-if (!scriptName)
-    return;
-
-char* cgiName = basename(scriptName);
 if (sameWord(cgiName, "hgc") || sameWord(cgiName, "hgTracks") || 
         sameWord(cgiName, "hgGene") || sameWord(cgiName, "hgTrackUi"))
 {
     // see https://support.google.com/analytics/answer/1136920?hl=en
     jsInlineF(
     "  function onExtAnchorClick(ev) {\n"
     "  /* user clicked an anchor: if external link, send event to Google analytics and navigate to the link */\n"
     "      var url = ev.currentTarget.href;\n"
     "      var hostname = null;\n"
     "      if (typeof URL===undefined) {\n"
     "          hostname = url.split('//')[1].split('/')[0];\n" // for MSIE
     "      } else {\n"
     "          var urlObj = new URL(url);\n"
     "          hostname = urlObj.hostname;\n"
     "          if (hostname.indexOf('.ncbi.')!==-1)\n" // for NCBI, we keep the first part of the pathname, as all DBs share the base URL
     "              hostname = hostname+'/'+urlObj.pathname.split('/')[1];\n"
     "      }\n"
     "      ga('send', 'event', 'outlink', hostname, url);\n" // beacon is default, see above.
     "\n"
     "      window.open(url);\n" // This may stop the previous ga event that is still running, but beacons should get through
     "      return false;\n"
     "  }\n"
     "  function gaTrackDb(db) {\n"
     "          if (!window.ga || ga.loaded)\n" // When using an Adblocker, the ga object does not exist
     "              return;\n"
     "          /* send db to ga as an event */\n"
     "          ga('send', 'event', 'hgTracks', 'load', getDb());\n"
     "}\n"
     );
     if (trackClicks)
         jsInlineF(
         "\n"
         "  $(document).ready(function() {\n"
         "      if (!window.ga || ga.loaded)\n" // When using an Adblocker, the ga object does not exist
         "          return;\n"
         "      var anchors = document.getElementsByTagName('a');\n"
         "      for (var i = 0; i < anchors.length; i++) { \n"
         "           var a = anchors[i];\n"
         "           var isExternal = (a.target.toLowerCase()==='_blank');\n"
         "           if (a.attributes.href && a.attributes.href.value!=='#' && isExternal)\n" // do not run on javascript links
         "               a.onclick = onExtAnchorClick;" // addEventHandler would not work here, the default click stops propagation.
         "      };\n"
         "      // on hgTracks: send an event with the current db, so we can report popularity of assemblies to NIH\n"
         "      if (typeof hgTracks !== 'undefined')\n"
         "          gaTrackDb(getDb());\n"
         "  });"
         );
     if (trackButtons)
         jsInlineF(
         "  $(document).ready(function() {\n"
         "      gaTrackButtons();\n" // see utils.js
         "  });");
 }
 }