3f08e8a24916a75afd749c152097f58344819a3a max Thu Mar 2 07:11:02 2023 -0800 Ignore the previous commit in code review, that was all wrong, I was looking at the wrong analytics page and thought it was working. The GA4 system is entirely different and the code now spread out over five source files. Also: The part of cart.c that outputs the <HEAD> is getting worse and worse. To test the new code, set the analyticsKey to the value in the cgi-bin-max sandbox and go to https://analytics.google.com/analytics/web/#/p356133243/realtime. All staff should have access (if not email me or Lou or Hiram), refs #30725 diff --git src/lib/htmshell.c src/lib/htmshell.c index 23fd280..750086e 100644 --- src/lib/htmshell.c +++ src/lib/htmshell.c @@ -15,30 +15,32 @@ #include "cheapcgi.h" #include "htmshell.h" #include "errAbort.h" #include "dnautil.h" #include "base64.h" jmp_buf htmlRecover; boolean htmlWarnBoxSetUpAlready=FALSE; static bool NoEscape = FALSE; static bool errorsNoHeader = FALSE; +static char *analyticsKey = NULL; + void htmlSuppressErrors() /* Do not output a http header for error messages. Makes sure that very early * errors are not shown back to the user but trigger a 500 error, */ { errorsNoHeader = TRUE; } void htmlNoEscape() { NoEscape = TRUE; } void htmlDoEscape() { NoEscape = FALSE; @@ -792,30 +794,36 @@ static char *htmlStyleSheet = NULL; void htmlSetStyleSheet(char *styleSheet) /* Set document wide style sheet by adding css name to HEAD part. * Needs to be called before htmlStart or htmShell. */ { htmlStyleSheet = styleSheet; } static char *htmlFormClass = NULL; void htmlSetFormClass(char *formClass) /* Set class in the BODY part. */ { htmlFormClass = formClass; } +void htmlSetGa4Key(char *key) +/* Set GA4 key. Needs to be called before htmlStart or htmShell. */ +{ +analyticsKey = key; +} + void htmlSetStyleTheme(char *style) /* Set theme style. Needs to be called before htmlStart or htmShell. */ { htmlStyleTheme = style; } static char *htmlBackground = NULL; void htmlSetBackground(char *imageFile) /* Set background - needs to be called before htmlStart * or htmShell. */ { htmlBackground = imageFile; } @@ -950,30 +958,31 @@ /* more secure method not used yet dyStringAppend(policy, "default-src 'self';"); dyStringAppend(policy, " child-src 'self';"); */ dyStringAppend(policy, " script-src 'self' blob:"); // Trick for backwards compatibility with browsers that understand CSP1 but not nonces (CSP2). dyStringAppend(policy, " 'unsafe-inline'"); // For browsers that DO understand nonces and CSP2, they ignore 'unsafe-inline' in script if nonce is present. char *noncePolicy=getNoncePolicy(); dyStringPrintf(policy, " %s", noncePolicy); freeMem(noncePolicy); dyStringAppend(policy, " code.jquery.com"); // used by hgIntegrator jsHelper and others dyStringAppend(policy, " www.google-analytics.com"); // used by google analytics +dyStringAppend(policy, " www.googletagmanager.com"); // used by google tag manager (new version of analytics) // cirm cdw lib and web browse dyStringAppend(policy, " www.samsarin.com/project/dagre-d3/latest/dagre-d3.js"); dyStringAppend(policy, " cdnjs.cloudflare.com/ajax/libs/d3/3.4.4/d3.min.js"); dyStringAppend(policy, " cdnjs.cloudflare.com/ajax/libs/jquery/1.12.1/jquery.min.js"); dyStringAppend(policy, " cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"); dyStringAppend(policy, " cdnjs.cloudflare.com/ajax/libs/bowser/1.6.1/bowser.min.js"); dyStringAppend(policy, " cdnjs.cloudflare.com/ajax/libs/jstree/3.3.4/jstree.min.js"); dyStringAppend(policy, " cdnjs.cloudflare.com/ajax/libs/jstree/3.3.7/jstree.min.js"); dyStringAppend(policy, " login.persona.org/include.js"); dyStringAppend(policy, " cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"); // expMatrix dyStringAppend(policy, " ajax.googleapis.com"); dyStringAppend(policy, " maxcdn.bootstrapcdn.com"); dyStringAppend(policy, " d3js.org/d3.v3.min.js"); // jsHelper @@ -1082,30 +1091,32 @@ fputs("<HEAD>\n", f); // CSP header generateCspMetaHeader(f); fputs(head, f); htmlFprintf(f,"<TITLE>%s</TITLE>\n", title); if (endsWith(title,"Login - UCSC Genome Browser")) fprintf(f,"\t<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html;CHARSET=iso-8859-1\">\n"); fprintf(f, "\t<META http-equiv=\"Content-Script-Type\" content=\"text/javascript\">\n"); if (htmlStyle != NULL) fputs(htmlStyle, f); if (htmlStyleSheet != NULL) fprintf(f,"<link href=\"%s\" rel=\"stylesheet\" type=\"text/css\">\n", htmlStyleSheet); if (htmlStyleTheme != NULL) fputs(htmlStyleTheme, f); +if (analyticsKey) + fprintf(f, "<script async src=\"https://www.googletagmanager.com/gtag/js?id=%s\"></script>\n", analyticsKey); fputs("</HEAD>\n\n",f); printBodyTag(f); htmlWarnBoxSetup(f); } void htmlStart(char *title) /* Write the start of an html from CGI */ { puts("Content-Type:text/html"); puts("\n"); _htmStartWithHead(stdout, "", title, TRUE, 1); }