mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Echo: Add config option to prevent duplicate page views for GA4 (#57619)
This commit is contained in:
parent
463f993186
commit
008c554d7f
@ -230,6 +230,9 @@ google_analytics_ua_id =
|
||||
# Google Analytics 4 tracking code, only enabled if you specify an id here
|
||||
google_analytics_4_id =
|
||||
|
||||
# When Google Analytics 4 Enhanced event measurement is enabled, we will try to avoid sending duplicate events and let Google Analytics 4 detect navigation changes, etc.
|
||||
google_analytics_4_send_manual_page_views = false
|
||||
|
||||
# Google Tag Manager ID, only enabled if you specify an id here
|
||||
google_tag_manager_id =
|
||||
|
||||
|
@ -237,6 +237,9 @@
|
||||
# Google Analytics 4 tracking code, only enabled if you specify an id here
|
||||
;google_analytics_4_id =
|
||||
|
||||
# When Google Analytics 4 Enhanced event measurement is enabled, we will try to avoid sending duplicate events and let Google Analytics 4 detect navigation changes, etc.
|
||||
;google_analytics_4_send_manual_page_views = false
|
||||
|
||||
# Google Tag Manager ID, only enabled if you specify an id here
|
||||
;google_tag_manager_id =
|
||||
|
||||
|
@ -211,6 +211,7 @@ export interface GrafanaConfig {
|
||||
secretsManagerPluginEnabled: boolean;
|
||||
googleAnalyticsId: string | undefined;
|
||||
googleAnalytics4Id: string | undefined;
|
||||
googleAnalytics4SendManualPageViews: boolean;
|
||||
rudderstackWriteKey: string | undefined;
|
||||
rudderstackDataPlaneUrl: string | undefined;
|
||||
rudderstackSdkUrl: string | undefined;
|
||||
|
@ -136,6 +136,7 @@ export class GrafanaBootConfig implements GrafanaConfig {
|
||||
};
|
||||
googleAnalyticsId: undefined;
|
||||
googleAnalytics4Id: undefined;
|
||||
googleAnalytics4SendManualPageViews = false;
|
||||
rudderstackWriteKey: undefined;
|
||||
rudderstackDataPlaneUrl: undefined;
|
||||
rudderstackSdkUrl: undefined;
|
||||
|
@ -8,27 +8,28 @@ import (
|
||||
)
|
||||
|
||||
type IndexViewData struct {
|
||||
User *CurrentUser
|
||||
Settings map[string]interface{}
|
||||
AppUrl string
|
||||
AppSubUrl string
|
||||
GoogleAnalyticsId string
|
||||
GoogleAnalytics4Id string
|
||||
GoogleTagManagerId string
|
||||
NavTree *navtree.NavTreeRoot
|
||||
BuildVersion string
|
||||
BuildCommit string
|
||||
Theme string
|
||||
NewGrafanaVersionExists bool
|
||||
NewGrafanaVersion string
|
||||
AppName string
|
||||
AppNameBodyClass string
|
||||
FavIcon template.URL
|
||||
AppleTouchIcon template.URL
|
||||
AppTitle string
|
||||
Sentry *setting.Sentry
|
||||
ContentDeliveryURL string
|
||||
LoadingLogo template.URL
|
||||
User *CurrentUser
|
||||
Settings map[string]interface{}
|
||||
AppUrl string
|
||||
AppSubUrl string
|
||||
GoogleAnalyticsId string
|
||||
GoogleAnalytics4Id string
|
||||
GoogleAnalytics4SendManualPageViews bool
|
||||
GoogleTagManagerId string
|
||||
NavTree *navtree.NavTreeRoot
|
||||
BuildVersion string
|
||||
BuildCommit string
|
||||
Theme string
|
||||
NewGrafanaVersionExists bool
|
||||
NewGrafanaVersion string
|
||||
AppName string
|
||||
AppNameBodyClass string
|
||||
FavIcon template.URL
|
||||
AppleTouchIcon template.URL
|
||||
AppTitle string
|
||||
Sentry *setting.Sentry
|
||||
ContentDeliveryURL string
|
||||
LoadingLogo template.URL
|
||||
// Nonce is a cryptographic identifier for use with Content Security Policy.
|
||||
Nonce string
|
||||
}
|
||||
|
@ -124,6 +124,7 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]i
|
||||
"queryHistoryEnabled": hs.Cfg.QueryHistoryEnabled,
|
||||
"googleAnalyticsId": setting.GoogleAnalyticsId,
|
||||
"googleAnalytics4Id": setting.GoogleAnalytics4Id,
|
||||
"GoogleAnalytics4SendManualPageViews": setting.GoogleAnalytics4SendManualPageViews,
|
||||
"rudderstackWriteKey": setting.RudderstackWriteKey,
|
||||
"rudderstackDataPlaneUrl": setting.RudderstackDataPlaneUrl,
|
||||
"rudderstackSdkUrl": setting.RudderstackSdkUrl,
|
||||
|
@ -98,27 +98,28 @@ func (hs *HTTPServer) setIndexViewData(c *models.ReqContext) (*dtos.IndexViewDat
|
||||
HelpFlags1: c.HelpFlags1,
|
||||
HasEditPermissionInFolders: hasEditPerm,
|
||||
},
|
||||
Settings: settings,
|
||||
Theme: prefs.Theme,
|
||||
AppUrl: appURL,
|
||||
AppSubUrl: appSubURL,
|
||||
GoogleAnalyticsId: setting.GoogleAnalyticsId,
|
||||
GoogleAnalytics4Id: setting.GoogleAnalytics4Id,
|
||||
GoogleTagManagerId: setting.GoogleTagManagerId,
|
||||
BuildVersion: setting.BuildVersion,
|
||||
BuildCommit: setting.BuildCommit,
|
||||
NewGrafanaVersion: hs.grafanaUpdateChecker.LatestVersion(),
|
||||
NewGrafanaVersionExists: hs.grafanaUpdateChecker.UpdateAvailable(),
|
||||
AppName: setting.ApplicationName,
|
||||
AppNameBodyClass: "app-grafana",
|
||||
FavIcon: "public/img/fav32.png",
|
||||
AppleTouchIcon: "public/img/apple-touch-icon.png",
|
||||
AppTitle: "Grafana",
|
||||
NavTree: navTree,
|
||||
Sentry: &hs.Cfg.Sentry,
|
||||
Nonce: c.RequestNonce,
|
||||
ContentDeliveryURL: hs.Cfg.GetContentDeliveryURL(hs.License.ContentDeliveryPrefix()),
|
||||
LoadingLogo: "public/img/grafana_icon.svg",
|
||||
Settings: settings,
|
||||
Theme: prefs.Theme,
|
||||
AppUrl: appURL,
|
||||
AppSubUrl: appSubURL,
|
||||
GoogleAnalyticsId: setting.GoogleAnalyticsId,
|
||||
GoogleAnalytics4Id: setting.GoogleAnalytics4Id,
|
||||
GoogleAnalytics4SendManualPageViews: setting.GoogleAnalytics4SendManualPageViews,
|
||||
GoogleTagManagerId: setting.GoogleTagManagerId,
|
||||
BuildVersion: setting.BuildVersion,
|
||||
BuildCommit: setting.BuildCommit,
|
||||
NewGrafanaVersion: hs.grafanaUpdateChecker.LatestVersion(),
|
||||
NewGrafanaVersionExists: hs.grafanaUpdateChecker.UpdateAvailable(),
|
||||
AppName: setting.ApplicationName,
|
||||
AppNameBodyClass: "app-grafana",
|
||||
FavIcon: "public/img/fav32.png",
|
||||
AppleTouchIcon: "public/img/apple-touch-icon.png",
|
||||
AppTitle: "Grafana",
|
||||
NavTree: navTree,
|
||||
Sentry: &hs.Cfg.Sentry,
|
||||
Nonce: c.RequestNonce,
|
||||
ContentDeliveryURL: hs.Cfg.GetContentDeliveryURL(hs.License.ContentDeliveryPrefix()),
|
||||
LoadingLogo: "public/img/grafana_icon.svg",
|
||||
}
|
||||
|
||||
if !hs.AccessControl.IsDisabled() {
|
||||
|
@ -137,13 +137,14 @@ var (
|
||||
appliedEnvOverrides []string
|
||||
|
||||
// analytics
|
||||
GoogleAnalyticsId string
|
||||
GoogleAnalytics4Id string
|
||||
GoogleTagManagerId string
|
||||
RudderstackDataPlaneUrl string
|
||||
RudderstackWriteKey string
|
||||
RudderstackSdkUrl string
|
||||
RudderstackConfigUrl string
|
||||
GoogleAnalyticsId string
|
||||
GoogleAnalytics4Id string
|
||||
GoogleAnalytics4SendManualPageViews bool
|
||||
GoogleTagManagerId string
|
||||
RudderstackDataPlaneUrl string
|
||||
RudderstackWriteKey string
|
||||
RudderstackSdkUrl string
|
||||
RudderstackConfigUrl string
|
||||
|
||||
// LDAP
|
||||
LDAPEnabled bool
|
||||
@ -995,6 +996,8 @@ func (cfg *Cfg) Load(args CommandLineArgs) error {
|
||||
cfg.CheckForPluginUpdates = analytics.Key("check_for_plugin_updates").MustBool(true)
|
||||
GoogleAnalyticsId = analytics.Key("google_analytics_ua_id").String()
|
||||
GoogleAnalytics4Id = analytics.Key("google_analytics_4_id").String()
|
||||
GoogleAnalytics4SendManualPageViews = analytics.Key("google_analytics_4_send_manual_page_views").MustBool(false)
|
||||
|
||||
GoogleTagManagerId = analytics.Key("google_tag_manager_id").String()
|
||||
RudderstackWriteKey = analytics.Key("rudderstack_write_key").String()
|
||||
RudderstackDataPlaneUrl = analytics.Key("rudderstack_data_plane_url").String()
|
||||
|
@ -268,6 +268,7 @@ function initEchoSrv() {
|
||||
registerEchoBackend(
|
||||
new GA4EchoBackend({
|
||||
googleAnalyticsId: config.googleAnalytics4Id,
|
||||
googleAnalytics4SendManualPageViews: config.googleAnalytics4SendManualPageViews,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -11,16 +11,17 @@ declare global {
|
||||
|
||||
export interface GA4EchoBackendOptions {
|
||||
googleAnalyticsId: string;
|
||||
googleAnalytics4SendManualPageViews: boolean;
|
||||
user?: CurrentUserDTO;
|
||||
}
|
||||
|
||||
export class GA4EchoBackend implements EchoBackend<PageviewEchoEvent, GA4EchoBackendOptions> {
|
||||
supportedEvents = [EchoEventType.Pageview];
|
||||
trackedUserId: number | null = null;
|
||||
googleAnalytics4SendManualPageViews = false;
|
||||
|
||||
constructor(public options: GA4EchoBackendOptions) {
|
||||
const url = `https://www.googletagmanager.com/gtag/js?id=${options.googleAnalyticsId}`;
|
||||
loadScript(url);
|
||||
loadScript(url, true);
|
||||
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
window.gtag = function gtag() {
|
||||
@ -28,12 +29,15 @@ export class GA4EchoBackend implements EchoBackend<PageviewEchoEvent, GA4EchoBac
|
||||
};
|
||||
window.gtag('js', new Date());
|
||||
|
||||
const configOptions: Gtag.CustomParams = {};
|
||||
const configOptions: Gtag.CustomParams = {
|
||||
page_path: window.location.pathname,
|
||||
};
|
||||
|
||||
if (options.user) {
|
||||
configOptions.user_id = getUserIdentifier(options.user);
|
||||
}
|
||||
|
||||
this.googleAnalytics4SendManualPageViews = options.googleAnalytics4SendManualPageViews;
|
||||
window.gtag('config', options.googleAnalyticsId, configOptions);
|
||||
}
|
||||
|
||||
@ -41,9 +45,10 @@ export class GA4EchoBackend implements EchoBackend<PageviewEchoEvent, GA4EchoBac
|
||||
if (!window.gtag) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.gtag('set', 'page_path', e.payload.page);
|
||||
window.gtag('event', 'page_view');
|
||||
// this should prevent duplicate events in case enhanced tracking is enabled
|
||||
if (this.googleAnalytics4SendManualPageViews) {
|
||||
window.gtag('event', 'page_view', { page_path: e.payload.page });
|
||||
}
|
||||
};
|
||||
|
||||
// Not using Echo buffering, addEvent above sends events to GA as soon as they appear
|
||||
|
@ -14,11 +14,12 @@ export function getUserIdentifier(user: CurrentUserDTO) {
|
||||
return user.email;
|
||||
}
|
||||
|
||||
export function loadScript(url: string) {
|
||||
export function loadScript(url: string, async = false) {
|
||||
return new Promise((resolve) => {
|
||||
const script = document.createElement('script');
|
||||
script.onload = resolve;
|
||||
script.src = url;
|
||||
script.async = async;
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user