FEATURE: Add Google Universal Analytics v4 as an option (#11123)
Per Google, sites are encouraged to upgrade from Universal Analytics v3 `analytics.js` to v4 `gtag.js` for Google Analytics tracking. We're giving admins the option to stay on the v3 API or migrate to v4. Admins can change the implementation they're using via the `ga_version` site setting. Eventually Google will deprecate v3, but our implementation gives admins the choice on what to use for now. We chose this implementation to make the change less error prone, as many site admins are using custom events via the v3 UA API. With the site stetting defaulted to `v3_analytics`, site analytics won't break until the admin is ready to make the migration. Additionally, in the v4 implementation, we do not enable automatic pageview tracking (on by default in the v4 API). Instead we rely on Discourse's page change API to report pageviews on transition to avoid double-tracking.
This commit is contained in:
parent
8f7e4f87ec
commit
09b8a61f65
|
@ -36,8 +36,11 @@ export default {
|
|||
return;
|
||||
}
|
||||
|
||||
// Also use Universal Analytics if it is present
|
||||
if (typeof window.ga !== "undefined") {
|
||||
// Use Universal Analytics v3 if it is present
|
||||
if (
|
||||
typeof window.ga !== "undefined" &&
|
||||
typeof window.gtag === "undefined"
|
||||
) {
|
||||
appEvents.on("page:changed", (data) => {
|
||||
if (!data.replacedOnlyQueryParams) {
|
||||
window.ga("send", "pageview", { page: data.url, title: data.title });
|
||||
|
@ -45,7 +48,19 @@ export default {
|
|||
});
|
||||
}
|
||||
|
||||
// And Google Tag Manager too
|
||||
// And Universal Analytics v4 if we're upgraded
|
||||
if (typeof window.gtag !== "undefined") {
|
||||
appEvents.on("page:changed", (data) => {
|
||||
if (!data.replacedOnlyQueryParams) {
|
||||
window.gtag("event", "page_view", {
|
||||
page_location: data.url,
|
||||
page_title: data.title,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Google Tag Manager too
|
||||
if (typeof window.dataLayer !== "undefined") {
|
||||
appEvents.on("page:changed", (data) => {
|
||||
if (!data.replacedOnlyQueryParams) {
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
// discourse-skip-module
|
||||
(function () {
|
||||
const gaDataElement = document.getElementById("data-ga-universal-analytics");
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
|
||||
window.gtag = function () {
|
||||
window.dataLayer.push(arguments);
|
||||
};
|
||||
window.gtag("js", new Date());
|
||||
|
||||
let autoLinkConfig = {};
|
||||
|
||||
if (gaDataElement.dataset.autoLinkDomains.length) {
|
||||
const autoLinkDomains = gaDataElement.dataset.autoLinkDomains.split("|");
|
||||
autoLinkConfig = {
|
||||
linker: {
|
||||
accept_incoming: true,
|
||||
domains: autoLinkDomains,
|
||||
},
|
||||
};
|
||||
}
|
||||
window.gtag("config", gaDataElement.dataset.trackingCode, {
|
||||
send_page_view: false,
|
||||
autoLinkConfig,
|
||||
});
|
||||
})();
|
|
@ -4,4 +4,9 @@
|
|||
auto_link_domains: SiteSetting.ga_universal_auto_link_domains
|
||||
} %>
|
||||
|
||||
<%= preload_script "google-universal-analytics" %>
|
||||
<% if SiteSetting.ga_version == "v3_analytics" %>
|
||||
<%= preload_script "google-universal-analytics-v3" %>
|
||||
<% elsif SiteSetting.ga_version == "v4_gtag" %>
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=<%= SiteSetting.ga_universal_tracking_code %>"></script>
|
||||
<%= preload_script "google-universal-analytics-v4" %>
|
||||
<% end %>
|
||||
|
|
|
@ -159,7 +159,8 @@ module Discourse
|
|||
markdown-it-bundle.js
|
||||
service-worker.js
|
||||
google-tag-manager.js
|
||||
google-universal-analytics.js
|
||||
google-universal-analytics-v3.js
|
||||
google-universal-analytics-v4.js
|
||||
start-discourse.js
|
||||
print-page.js
|
||||
omniauth-complete.js
|
||||
|
|
|
@ -1555,9 +1555,10 @@ en:
|
|||
pending_users_reminder_delay: "Notify moderators if new users have been waiting for approval for longer than this many hours. Set to -1 to disable notifications."
|
||||
persistent_sessions: "Users will remain logged in when the web browser is closed"
|
||||
maximum_session_age: "User will remain logged in for n hours since last visit"
|
||||
ga_universal_tracking_code: "Google Universal Analytics (analytics.js) tracking code ID, eg: UA-12345678-9; see <a href='https://google.com/analytics' target='_blank'>https://google.com/analytics</a>"
|
||||
ga_universal_domain_name: "Google Universal Analytics (analytics.js) domain name, eg: mysite.com; see <a href='https://google.com/analytics' target='_blank'>https://google.com/analytics</a>"
|
||||
ga_universal_auto_link_domains: "Enable Google Universal Analytics (analytics.js) cross-domain tracking. Outgoing links to these domains will have the client id added to them. See <a href='https://support.google.com/analytics/answer/1034342?hl=en' target='_blank'>Google's Cross-Domain Tracking guide.</a>"
|
||||
ga_version: "Version of Google Universal Analytics to use: v3 (analytics.js), v4 (gtag)"
|
||||
ga_universal_tracking_code: "Google Universal Analytics tracking code ID, eg: UA-12345678-9; see <a href='https://google.com/analytics' target='_blank'>https://google.com/analytics</a>"
|
||||
ga_universal_domain_name: "Google Universal Analytics domain name, eg: mysite.com; see <a href='https://google.com/analytics' target='_blank'>https://google.com/analytics</a>"
|
||||
ga_universal_auto_link_domains: "Enable Google Universal Analytics cross-domain tracking. Outgoing links to these domains will have the client id added to them. See <a href='https://support.google.com/analytics/answer/1034342?hl=en' target='_blank'>Google's Cross-Domain Tracking guide.</a>"
|
||||
gtm_container_id: "Google Tag Manager container id. eg: GTM-ABCDEF. <br/>Note: Third-party scripts loaded by GTM may need to be allowlisted in 'content security policy script src'."
|
||||
enable_escaped_fragments: "Fall back to Google's Ajax-Crawling API if no webcrawler is detected. See <a href='https://developers.google.com/webmasters/ajax-crawling/docs/learn-more' target='_blank'>https://developers.google.com/webmasters/ajax-crawling/docs/learn-more</a>"
|
||||
moderators_manage_categories_and_groups: "Allow moderators to manage categories and groups"
|
||||
|
|
|
@ -139,6 +139,12 @@ basic:
|
|||
default: 365
|
||||
min: 7
|
||||
max: 36500
|
||||
ga_version:
|
||||
type: enum
|
||||
default: v3_analytics
|
||||
choices:
|
||||
- v3_analytics
|
||||
- v4_gtag
|
||||
ga_universal_tracking_code:
|
||||
client: true
|
||||
default: ""
|
||||
|
|
|
@ -56,7 +56,9 @@ class ContentSecurityPolicy
|
|||
].tap do |sources|
|
||||
sources << :report_sample if SiteSetting.content_security_policy_collect_reports
|
||||
sources << :unsafe_eval if Rails.env.development? # TODO remove this once we have proper source maps in dev
|
||||
# we need analytics.js still as gtag/js is a script wrapper for it
|
||||
sources << 'https://www.google-analytics.com/analytics.js' if SiteSetting.ga_universal_tracking_code.present?
|
||||
sources << 'https://www.googletagmanager.com/gtag/js' if SiteSetting.ga_universal_tracking_code.present? && SiteSetting.ga_version == "v4_gtag"
|
||||
sources << 'https://www.googletagmanager.com/gtm.js' if SiteSetting.gtm_container_id.present?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -52,7 +52,8 @@ class DiscourseJsProcessor
|
|||
wizard-start
|
||||
onpopstate-handler
|
||||
google-tag-manager
|
||||
google-universal-analytics
|
||||
google-universal-analytics-v3
|
||||
google-universal-analytics-v4
|
||||
activate-account
|
||||
auto-redirect
|
||||
embed-application
|
||||
|
|
|
@ -69,12 +69,30 @@ describe ContentSecurityPolicy do
|
|||
expect(script_srcs).to include("'report-sample'")
|
||||
end
|
||||
|
||||
it 'allowlists Google Analytics and Tag Manager when integrated' do
|
||||
context 'for Google Analytics' do
|
||||
before do
|
||||
SiteSetting.ga_universal_tracking_code = 'UA-12345678-9'
|
||||
SiteSetting.gtm_container_id = 'GTM-ABCDEF'
|
||||
end
|
||||
|
||||
it 'allowlists Google Analytics v3 when integrated' do
|
||||
script_srcs = parse(policy)['script-src']
|
||||
expect(script_srcs).to include('https://www.google-analytics.com/analytics.js')
|
||||
expect(script_srcs).not_to include('https://www.googletagmanager.com/gtag/js')
|
||||
end
|
||||
|
||||
it 'allowlists Google Analytics v4 when integrated' do
|
||||
SiteSetting.ga_version = 'v4_gtag'
|
||||
|
||||
script_srcs = parse(policy)['script-src']
|
||||
expect(script_srcs).to include('https://www.google-analytics.com/analytics.js')
|
||||
expect(script_srcs).to include('https://www.googletagmanager.com/gtag/js')
|
||||
end
|
||||
end
|
||||
|
||||
it 'allowlists Google Tag Manager when integrated' do
|
||||
SiteSetting.gtm_container_id = 'GTM-ABCDEF'
|
||||
|
||||
script_srcs = parse(policy)['script-src']
|
||||
expect(script_srcs).to include('https://www.googletagmanager.com/gtm.js')
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue