Skip to content

Commit

Permalink
Introduce GA4 alongside UA analytics (oppia#16038)
Browse files Browse the repository at this point in the history
* temp changes

* update per constants

* update constants; increase build memory limit

* fix constants

* import -> require for constants

* lint fixes

* lint errors

* Revert "lint errors"

This reverts commit 8a991c2.

* Revert "lint fixes"

This reverts commit b55adf2.

* Revert "import -> require for constants"

This reverts commit abf5033.

* add local constatn in webpack.common.config.ts

* update config from deploy data

* undo release_constants changes

* address comments

* move constants to a separate JSON

* address comments

* move some plugins to prod config

* address comments

* sync changes with the release scripts

* add comment
  • Loading branch information
Kevin Thomas authored Sep 15, 2022
1 parent 84bba23 commit 127b77f
Show file tree
Hide file tree
Showing 16 changed files with 198 additions and 46 deletions.
6 changes: 6 additions & 0 deletions assets/analytics-constants.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"CAN_SEND_ANALYTICS_EVENTS": false,
"GA_ANALYTICS_ID": "",
"UA_ANALYTICS_ID": "",
"SITE_NAME_FOR_ANALYTICS": ""
}
8 changes: 0 additions & 8 deletions assets/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@
*/

export default {
// Whether to allow custom event reporting to Google Analytics.
// Mock gtag function is used when disabled.
"CAN_SEND_ANALYTICS_EVENTS": false,

// The term 'staging' is used instead of the classroom url fragment field
// in the URL for topics that are not yet attached to a classroom.
"CLASSROOM_URL_FRAGMENT_FOR_UNATTACHED_TOPICS": "staging",
Expand Down Expand Up @@ -6008,10 +6004,6 @@ export default {
}
},

// Data required for Google Analytics.
"ANALYTICS_ID": "",
"SITE_NAME_FOR_ANALYTICS": "",

// Data required for Firebase authentication.
//
// NOTE TO RELEASE COORDINATORS: Please change these to the production values,
Expand Down
21 changes: 16 additions & 5 deletions core/templates/google-analytics.initializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,38 @@
* @fileoverview Initialization of Google Analytics (gtag.js).
*/

import constants from 'assets/constants';

import analyticsConstants from 'analytics-constants';

initializeGoogleAnalytics();

export function initializeGoogleAnalytics() {
if (!constants.CAN_SEND_ANALYTICS_EVENTS) {
if (!analyticsConstants.CAN_SEND_ANALYTICS_EVENTS) {
// Mock gtag function will prevent sending analytics to google.
window.gtag = function() {}
return;
}

if (constants.ANALYTICS_ID && constants.SITE_NAME_FOR_ANALYTICS) {
if (
analyticsConstants.GA_ANALYTICS_ID &&
analyticsConstants.UA_ANALYTICS_ID &&
analyticsConstants.SITE_NAME_FOR_ANALYTICS
) {
// Reference doc:
// https://developers.google.com/analytics/devguides/collection/gtagjs
window.dataLayer = window.dataLayer || [];
window.gtag = function(): void {
window.dataLayer.push(arguments);
}
gtag('set', 'linker', {
'domains': [constants.SITE_NAME_FOR_ANALYTICS]
'domains': [analyticsConstants.SITE_NAME_FOR_ANALYTICS]
});
gtag('js', new Date());
gtag('config', constants.ANALYTICS_ID, {
gtag('config', analyticsConstants.GA_ANALYTICS_ID, {
'anonymize_ip': true,
'forceSSL': true,
});
gtag('config', analyticsConstants.UA_ANALYTICS_ID, {
'anonymize_ip': true,
'forceSSL': true,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { downgradeInjectable } from '@angular/upgrade/static';
import { AppConstants } from 'app.constants';
import { WindowRef } from 'services/contextual/window-ref.service';
import { SiteAnalyticsService } from 'services/site-analytics.service';
import analyticsConstants from 'analytics-constants';

@Injectable({
providedIn: 'root'
Expand All @@ -39,7 +39,7 @@ export class DeleteAccountBackendApiService {
setTimeout(() => {
this.windowRef.nativeWindow.location.href = (
'/logout?redirect_url=/pending-account-deletion');
}, AppConstants.CAN_SEND_ANALYTICS_EVENTS ? 150 : 0);
}, analyticsConstants.CAN_SEND_ANALYTICS_EVENTS ? 150 : 0);
});
}
}
Expand Down
10 changes: 9 additions & 1 deletion core/templates/pages/header_js_libs.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
<script async src="https://www.googletagmanager.com/gtag/js"></script>
<% if (CAN_SEND_ANALYTICS_EVENTS) { %>
<!--
Note that gtag.js is downloaded for each script tag. However, the
downloaded files are different because we use different IDs in the
query parameters to download them.
-->
<script async src="https://www.googletagmanager.com/gtag/js?id=<%= GA_ANALYTICS_ID %>"></script>
<script async src="https://www.googletagmanager.com/gtag/js?id=<%= UA_ANALYTICS_ID %>"></script>
<% } %>
<!-- This code is used for inserting webpack bundles
https://github.com/jantimon/html-webpack-plugin#writing-your-own-templates -->
<% for (var chunk in htmlWebpackPlugin.files.js) { %>
Expand Down
3 changes: 2 additions & 1 deletion core/templates/pages/signup-page/signup-page.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { UtilsService } from 'services/utils.service';
import { LicenseExplanationModalComponent } from './modals/license-explanation-modal.component';
import { RegistrationSessionExpiredModalComponent } from './modals/registration-session-expired-modal.component';
import { SignupPageBackendApiService } from './services/signup-page-backend-api.service';
import analyticsConstants from 'analytics-constants';

@Component({
selector: 'oppia-signup-page',
Expand Down Expand Up @@ -214,7 +215,7 @@ export class SignupPageComponent {
setTimeout(() => {
this.windowRef.nativeWindow.location.href = (
this.utilsService.getSafeReturnUrl(returnUrl));
}, AppConstants.CAN_SEND_ANALYTICS_EVENTS ? 150 : 0);
}, analyticsConstants.CAN_SEND_ANALYTICS_EVENTS ? 150 : 0);
}, (rejection) => {
if (rejection && rejection.status_code === 401) {
this.showRegistrationSessionExpiredModal();
Expand Down
4 changes: 0 additions & 4 deletions core/tests/build_sources/assets/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@
* functions.
*/
var constants = {
// Whether to allow custom event reporting to Google Analytics.
// Mock gtag function is used when disabled.
"CAN_SEND_ANALYTICS_EVENTS": false,

"ALL_CATEGORIES": ["Algebra", "Algorithms", "Architecture", "Arithmetic",
"Art", "Astronomy", "Biology", "Business", "Calculus", "Chemistry",
"Combinatorics", "Computing", "Economics", "Education", "Engineering",
Expand Down
2 changes: 2 additions & 0 deletions scripts/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@
WEBPACK_DEV_SOURCE_MAPS_CONFIG = 'webpack.dev.sourcemap.config.ts'
WEBPACK_PROD_CONFIG = 'webpack.prod.config.ts'
WEBPACK_PROD_SOURCE_MAPS_CONFIG = 'webpack.prod.sourcemap.config.ts'
ANALYTICS_CONSTANTS_FILE_PATH = (
os.path.join('assets', 'analytics-constants.json'))

PORTSERVER_SOCKET_FILEPATH = os.path.join(os.getcwd(), 'portserver.socket')

Expand Down
3 changes: 1 addition & 2 deletions scripts/pre_commit_hook.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@
b'REQUIRE_EMAIL_ON_MODERATOR_ACTION', b'EMAIL_SERVICE_PROVIDER',
b'SYSTEM_EMAIL_NAME', b'MAILGUN_DOMAIN_NAME']
KEYS_UPDATED_IN_CONSTANTS = [
b'CAN_SEND_ANALYTICS_EVENTS', b'SITE_FEEDBACK_FORM_URL',
b'ANALYTICS_ID', b'SITE_NAME_FOR_ANALYTICS', b'FIREBASE_CONFIG_API_KEY',
b'SITE_FEEDBACK_FORM_URL', b'FIREBASE_CONFIG_API_KEY',
b'FIREBASE_CONFIG_APP_ID', b'FIREBASE_CONFIG_AUTH_DOMAIN',
b'FIREBASE_CONFIG_MESSAGING_SENDER_ID', b'FIREBASE_CONFIG_PROJECT_ID',
b'FIREBASE_CONFIG_STORAGE_BUCKET', b'FIREBASE_CONFIG_GOOGLE_CLIENT_ID']
Expand Down
4 changes: 2 additions & 2 deletions scripts/pre_commit_hook_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,8 @@ def mock_check_output(cmd_tokens):
b'-CLASSIFIERS_DIR = os.path.join(\'.\', \'dir1\')\n'
b'+CLASSIFIERS_DIR = os.path.join(\'.\', \'dir2\')\n')
return (
b'- "ANALYTICS_ID": "",\n'
b'+ "ANALYTICS_ID": "change",\n')
b'- "FIREBASE_CONFIG_API_KEY": "fake-api-key",\n'
b'+ "FIREBASE_CONFIG_API_KEY": "changed-api-key",\n')
check_output_swap = self.swap(
subprocess, 'check_output', mock_check_output)
with check_output_swap, self.assertRaisesRegex(
Expand Down
50 changes: 48 additions & 2 deletions scripts/release_scripts/update_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ def apply_changes_based_on_config(
line_number for (line_number, line) in enumerate(local_lines)
if line.startswith(match_result.group(1))]
assert len(matching_local_line_numbers) == 1, (
'Could not find correct number of lines in %s matching: %s' %
(local_filename, config_line))
'Could not find correct number of lines in %s matching: %s, %s' %
(local_filename, config_line, matching_local_line_numbers))
local_line_numbers.append(matching_local_line_numbers[0])

# Then, apply the changes.
Expand Down Expand Up @@ -305,6 +305,45 @@ def add_mailchimp_api_key(release_feconf_path):
f.write(line)


def update_analytics_constants_based_on_config(
release_analytics_constants_path,
analytics_constants_config_path
):
"""Updates the GA4 and UA IDs in the analytics constants JSON file.
Args:
release_analytics_constants_path: str. The path to constants file.
analytics_constants_config_path: str. The path to constants config file.
"""
with utils.open_file(analytics_constants_config_path, 'r') as config_file:
config_file_contents = config_file.read()
ga_analytics_id = re.search(
r'"GA_ANALYTICS_ID": "(.*)"', config_file_contents).group(1)
ua_analytics_id = re.search(
r'"UA_ANALYTICS_ID": "(.*)"', config_file_contents).group(1)
site_name_for_analytics = re.search(
r'"SITE_NAME_FOR_ANALYTICS": "(.*)"', config_file_contents).group(1)
can_send_analytics_events = re.search(
r'"CAN_SEND_ANALYTICS_EVENTS": (true|false)',
config_file_contents).group(1)
common.inplace_replace_file(
release_analytics_constants_path,
'"GA_ANALYTICS_ID": ""',
'"GA_ANALYTICS_ID": "%s"' % ga_analytics_id)
common.inplace_replace_file(
release_analytics_constants_path,
'"UA_ANALYTICS_ID": ""',
'"UA_ANALYTICS_ID": "%s"' % ua_analytics_id)
common.inplace_replace_file(
release_analytics_constants_path,
'"SITE_NAME_FOR_ANALYTICS": ""',
'"SITE_NAME_FOR_ANALYTICS": "%s"' % site_name_for_analytics)
common.inplace_replace_file(
release_analytics_constants_path,
'"CAN_SEND_ANALYTICS_EVENTS": false',
'"CAN_SEND_ANALYTICS_EVENTS": %s' % can_send_analytics_events)


def main(args=None):
"""Updates the files corresponding to LOCAL_FECONF_PATH and
LOCAL_CONSTANTS_PATH after doing the prerequisite checks.
Expand All @@ -316,13 +355,17 @@ def main(args=None):
options.deploy_data_path, 'feconf_updates.config')
constants_config_path = os.path.join(
options.deploy_data_path, 'constants_updates.config')
analytics_constants_config_path = os.path.join(
options.deploy_data_path, 'analytics_constants_updates.config')

release_feconf_path = os.path.join(
options.release_dir_path, common.FECONF_PATH)
release_constants_path = os.path.join(
options.release_dir_path, common.CONSTANTS_FILE_PATH)
release_app_dev_yaml_path = os.path.join(
options.release_dir_path, common.APP_DEV_YAML_PATH)
release_analytics_constants_path = os.path.join(
options.release_dir_path, common.ANALYTICS_CONSTANTS_FILE_PATH)

if options.prompt_for_mailgun_and_terms_update:
try:
Expand All @@ -339,6 +382,9 @@ def main(args=None):
apply_changes_based_on_config(
release_constants_path, constants_config_path, CONSTANTS_REGEX)
update_app_yaml(release_app_dev_yaml_path, feconf_config_path)
update_analytics_constants_based_on_config(
release_analytics_constants_path,
analytics_constants_config_path)
verify_config_files(
release_feconf_path,
release_app_dev_yaml_path,
Expand Down
Loading

0 comments on commit 127b77f

Please sign in to comment.