ngx-google-analytics
Version:
A simple ng-9 wrapper to load Google Analytics dependency by angular way
686 lines (668 loc) • 27.6 kB
JavaScript
import * as i0 from '@angular/core';
import { Directive, Input, InjectionToken, inject, isDevMode, Injectable, Inject, Optional, Host, APP_INITIALIZER, APP_BOOTSTRAP_LISTENER, NgModule } from '@angular/core';
import { fromEvent } from 'rxjs';
import { DOCUMENT, CommonModule } from '@angular/common';
import { __awaiter } from 'tslib';
import { Router, NavigationEnd } from '@angular/router';
import { filter, skip } from 'rxjs/operators';
class GaEventCategoryDirective {
constructor() { }
}
GaEventCategoryDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: GaEventCategoryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
GaEventCategoryDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.2", type: GaEventCategoryDirective, selector: "[gaEvent][gaCategory],\n [gaCategory]", inputs: { gaCategory: "gaCategory" }, exportAs: ["gaCategory"], ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: GaEventCategoryDirective, decorators: [{
type: Directive,
args: [{
selector: `[gaEvent][gaCategory],
[gaCategory]`,
exportAs: 'gaCategory'
}]
}], ctorParameters: function () { return []; }, propDecorators: { gaCategory: [{
type: Input
}] } });
/**
* Provide a Injection Token to global settings.
*/
const NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN = new InjectionToken('ngx-google-analytics-settings', {
factory: () => ({ trackingCode: '', enableTracing: false })
});
/**
* Provide DOM Window reference.
*/
const NGX_WINDOW = new InjectionToken('ngx-window', {
providedIn: 'root',
factory: () => {
const { defaultView } = inject(DOCUMENT);
if (!defaultView) {
throw new Error('Window is not available');
}
return defaultView;
},
});
/**
* Check if there is some global function called gtag on Window object, or create an empty function to doesn't brake codes...
*/
function getDataLayerFn(window) {
return (window)
? window['dataLayer'] = window['dataLayer'] || []
: null;
}
/**
* Provides an injection token to access Google Analytics DataLayer Collection
*/
const NGX_DATA_LAYER = new InjectionToken('ngx-data-layer', {
providedIn: 'root',
factory: () => getDataLayerFn(inject(NGX_WINDOW))
});
/**
* Check if there is some global function called gtag on Window object, or create an empty function to doesn't brake codes...
*/
function getGtagFn(window, dataLayer) {
return (window)
? window['gtag'] = window['gtag'] || function () {
dataLayer.push(arguments);
}
: null;
}
/**
* Provides an injection token to access Google Analytics Gtag Function
*/
const NGX_GTAG_FN = new InjectionToken('ngx-gtag-fn', {
providedIn: 'root',
factory: () => getGtagFn(inject(NGX_WINDOW), inject(NGX_DATA_LAYER))
});
class GoogleAnalyticsService {
constructor(settings, _document, _gtag) {
this.settings = settings;
this._document = _document;
this._gtag = _gtag;
}
get document() {
return this._document;
}
throw(err) {
if ((this.settings.enableTracing || isDevMode()) && console && console.error) {
console.error(err);
}
}
/** @todo Change this to `Object.fromEntity()` in the future... */
toKeyValue(map) {
return (map.size > 0)
? Array.from(map).reduce((obj, [key, value]) => Object.defineProperty(obj, key, { value, enumerable: true }), {})
: undefined;
}
/**
* Call native GA Tag
*/
gtag(...args) {
try {
this._gtag(...args.filter(x => x !== undefined));
}
catch (err) {
this.throw(err);
}
}
/**
* Send an event trigger to GA. It is the same as call:
* ```js
* gtag('event', 'video_auto_play_start', {
* 'event_label': 'My promotional video',
* 'event_category': 'video_auto_play'
* });
* ```
*
* @param action 'video_auto_play_start'
* @param category 'video_auto_play'
* @param label 'My promotional video'
* @param value An value to measure something
* @param interaction If user interaction is performed
*/
event(action, category, label, value, interaction, options) {
try {
const opt = new Map();
if (category) {
opt.set('event_category', category);
}
if (label) {
opt.set('event_label', label);
}
if (value) {
opt.set('value', value);
}
if (interaction !== undefined) {
opt.set('interaction', interaction);
}
if (options) {
Object
.entries(options)
.map(([key, value]) => opt.set(key, value));
}
const params = this.toKeyValue(opt);
if (params) {
this.gtag('event', action, params);
}
else {
this.gtag('event', action);
}
}
catch (error) {
this.throw(error);
}
}
/**
* Send an page view event. This is the same as
*
* ```js
* gtag('config', 'GA_TRACKING_ID', {
* 'page_title' : 'Homepage',
* 'page_path': '/home'
* });
* ```
*
* The tracking ID is injected automatically by Inject Token NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN
*
* @param path /home
* @param title Homepage
* @param location '{ page_location }'
* @param options '{ ... custom dimentions }'
*/
pageView(path, title, location, options) {
try {
const opt = new Map([['page_path', path]]);
if (title) {
opt.set('page_title', title);
}
if (location || this.document) {
opt.set('page_location', (location || this.document.location.href));
}
if (options) {
Object
.entries(options)
.map(([key, value]) => opt.set(key, value));
}
this.gtag('config', this.settings.trackingCode, this.toKeyValue(opt));
}
catch (error) {
this.throw(error);
}
}
/**
* Send an event to report a App Page View. It is the same as
*
* ```js
* gtag('event', 'screen_view', {
* 'app_name': 'myAppName',
* 'screen_name' : 'Home'
* });
*
* ```
*
* @param screen 'screen_name'
* @param appName 'app_name'
* @param appId 'app_id'
* @param appVersion 'app_version'
* @param installerId 'app_installer_id'
*/
appView(screen, appName, appId, appVersion, installerId) {
try {
const opt = new Map([['screen_name', screen], ['app_name', appName]]);
if (appId) {
opt.set('app_id', appId);
}
if (appVersion) {
opt.set('app_version', appVersion);
}
if (installerId) {
opt.set('app_installer_id', installerId);
}
this.gtag('event', 'screen_view', this.toKeyValue(opt));
}
catch (error) {
this.throw(error);
}
}
/**
* Defines persistent values on GoogleAnalytics
*
* @see https://developers.google.com/analytics/devguides/collection/gtagjs/setting-values
*
* ```js
* gtag('set', {
* 'currency': 'USD',
* 'country': 'US'
* });
* ```
*/
set(...options) {
try {
this._gtag('set', ...options);
}
catch (err) {
this.throw(err);
}
}
/**
* Send an event to GA to report an application error. It is the same as
*
* ```js
* gtag('event', 'exception', {
* 'description': 'error_description',
* 'fatal': false // set to true if the error is fatal
* });
* ```
*
* @param description 'error_description'
* @param fatal set to true if the error is fatal
*/
exception(description, fatal) {
try {
const opt = new Map();
if (description) {
opt.set('description', description);
}
if (fatal) {
opt.set('fatal', fatal);
}
const params = this.toKeyValue(opt);
if (params) {
this.gtag('event', 'exception', this.toKeyValue(opt));
}
else {
this.gtag('event', 'exception');
}
}
catch (error) {
this.throw(error);
}
}
}
GoogleAnalyticsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: GoogleAnalyticsService, deps: [{ token: NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN }, { token: DOCUMENT }, { token: NGX_GTAG_FN }], target: i0.ɵɵFactoryTarget.Injectable });
GoogleAnalyticsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: GoogleAnalyticsService, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: GoogleAnalyticsService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: function () {
return [{ type: undefined, decorators: [{
type: Inject,
args: [NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [NGX_GTAG_FN]
}] }];
} });
class GaEventDirective {
constructor(gaCategoryDirective, gaService, settings, el) {
this.gaCategoryDirective = gaCategoryDirective;
this.gaService = gaService;
this.settings = settings;
this.el = el;
this.gaBind = 'click';
}
set gaBind(gaBind) {
if (this.bindSubscription) {
this.bindSubscription.unsubscribe();
}
this._gaBind = gaBind;
this.bindSubscription = fromEvent(this.el.nativeElement, gaBind).subscribe(() => this.trigger());
}
get gaBind() {
return this._gaBind;
}
ngOnDestroy() {
if (this.bindSubscription) {
this.bindSubscription.unsubscribe();
}
}
trigger() {
try {
// Observação: não é obrigatório especificar uma categoria, uma etiqueta ou um valor. Consulte Eventos padrão do Google Analytics abaixo.
// if (!this.$gaCategoryDirective) {
// throw new Error('You must provide a gaCategory attribute w/ gaEvent Directive.');
// }
if (!this.gaAction && !this.gaEvent) {
throw new Error('You must provide a gaAction attribute to identify this event.');
}
this.gaService
.event(this.gaAction || this.gaEvent, (this.gaCategoryDirective) ? this.gaCategoryDirective.gaCategory : undefined, this.gaLabel || this.label, this.gaValue, this.gaInteraction);
}
catch (err) {
this.throw(err);
}
}
throw(err) {
if ((isDevMode() || this.settings.enableTracing) && console && console.warn) {
console.warn(err);
}
}
}
GaEventDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: GaEventDirective, deps: [{ token: GaEventCategoryDirective, optional: true }, { token: GoogleAnalyticsService }, { token: NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
GaEventDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.2", type: GaEventDirective, selector: "[gaEvent]", inputs: { gaAction: "gaAction", gaLabel: "gaLabel", label: "label", gaValue: "gaValue", gaInteraction: "gaInteraction", gaEvent: "gaEvent", gaBind: "gaBind" }, exportAs: ["gaEvent"], ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: GaEventDirective, decorators: [{
type: Directive,
args: [{
selector: `[gaEvent]`,
exportAs: 'gaEvent'
}]
}], ctorParameters: function () {
return [{ type: GaEventCategoryDirective, decorators: [{
type: Optional
}] }, { type: GoogleAnalyticsService }, { type: undefined, decorators: [{
type: Inject,
args: [NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN]
}] }, { type: i0.ElementRef }];
}, propDecorators: { gaAction: [{
type: Input
}], gaLabel: [{
type: Input
}], label: [{
type: Input
}], gaValue: [{
type: Input
}], gaInteraction: [{
type: Input
}], gaEvent: [{
type: Input
}], gaBind: [{
type: Input
}] } });
class GaEventFormInputDirective {
constructor(gaEvent) {
this.gaEvent = gaEvent;
this.gaBind = 'focus';
}
set gaBind(bind) {
if (this.gaEvent) {
this.gaEvent.gaBind = bind;
}
}
}
GaEventFormInputDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: GaEventFormInputDirective, deps: [{ token: GaEventDirective, host: true, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
GaEventFormInputDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.2", type: GaEventFormInputDirective, selector: "input[gaEvent],\n select[gaEvent],\n textarea[gaEvent]", inputs: { gaBind: "gaBind" }, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: GaEventFormInputDirective, decorators: [{
type: Directive,
args: [{
selector: `input[gaEvent],
select[gaEvent],
textarea[gaEvent]`
}]
}], ctorParameters: function () {
return [{ type: GaEventDirective, decorators: [{
type: Host
}, {
type: Optional
}] }];
}, propDecorators: { gaBind: [{
type: Input
}] } });
var GaActionEnum;
(function (GaActionEnum) {
GaActionEnum["ADD_PAYMENT_INFO"] = "add_payment_info";
GaActionEnum["ADD_TO_CART"] = "add_to_cart";
GaActionEnum["ADD_TO_WISHLIST"] = "add_to_wishlist";
GaActionEnum["BEGIN_CHECKOUT"] = "begin_checkout";
GaActionEnum["CHECKOUT_PROGRESS"] = "checkout_progress";
GaActionEnum["GENERATE_LEAD"] = "generate_lead";
GaActionEnum["LOGIN"] = "login";
GaActionEnum["PURCHASE"] = "purchase";
GaActionEnum["REFUND"] = "refund";
GaActionEnum["REMOVE_FROM_CART"] = "remove_from_cart";
GaActionEnum["SEARCH"] = "search";
GaActionEnum["SELECT_CONTENT"] = "select_content";
GaActionEnum["SET_CHECKOUT_OPTION"] = "set_checkout_option";
GaActionEnum["SHARE"] = "share";
GaActionEnum["SIGN_UP"] = "sign_up";
GaActionEnum["VIEW_ITEM"] = "view_item";
GaActionEnum["VIEW_ITEM_LIST"] = "view_item_list";
GaActionEnum["VIEW_PROMOTION"] = "view_promotion";
GaActionEnum["VIEW_SEARCH_RESULT"] = "view_search_results";
GaActionEnum["VIEW_SEARCH_RESULTS"] = "view_search_results";
})(GaActionEnum || (GaActionEnum = {}));
/**
* Provide a DI Configuration to attach GA Initialization at Angular Startup Cycle.
*/
const NGX_GOOGLE_ANALYTICS_INITIALIZER_PROVIDER = {
provide: APP_INITIALIZER,
multi: true,
useFactory: GoogleAnalyticsInitializer,
deps: [
NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN,
NGX_GTAG_FN,
DOCUMENT
]
};
/**
* Create a script element on DOM and link it to Google Analytics tracking code URI.
* After that, execute exactly same init process as tracking snippet code.
*/
function GoogleAnalyticsInitializer(settings, gtag, document) {
return () => __awaiter(this, void 0, void 0, function* () {
var _a;
if (!settings.trackingCode) {
if (!isDevMode()) {
console.error('Empty tracking code for Google Analytics. Make sure to provide one when initializing NgxGoogleAnalyticsModule.');
}
return;
}
if (!gtag) {
if (!isDevMode()) {
console.error('Was not possible create or read gtag() fn. Make sure this module is running on a Browser w/ access to Window interface.');
}
return;
}
if (!document) {
if (!isDevMode()) {
console.error('Was not possible to access Document interface. Make sure this module is running on a Browser w/ access do Document interface.');
}
}
// Set default ga.js uri
settings.uri = settings.uri || `https://www.googletagmanager.com/gtag/js?id=${settings.trackingCode}`;
// these commands should run first!
settings.initCommands = (_a = settings === null || settings === void 0 ? void 0 : settings.initCommands) !== null && _a !== void 0 ? _a : [];
// assert config command
if (!settings.initCommands.find(x => x.command === 'config')) {
settings.initCommands.unshift({ command: 'config', values: [settings.trackingCode] });
}
// assert js command
if (!settings.initCommands.find(x => x.command === 'js')) {
settings.initCommands.unshift({ command: 'js', values: [new Date()] });
}
for (const command of settings.initCommands) {
gtag(command.command, ...command.values);
}
const s = document.createElement('script');
s.async = true;
s.src = settings.uri;
if (settings.nonce) {
s.setAttribute('nonce', settings.nonce);
}
const head = document.getElementsByTagName('head')[0];
head.appendChild(s);
});
}
/**
* Provide a Injection Token to global settings.
*/
const NGX_GOOGLE_ANALYTICS_ROUTING_SETTINGS_TOKEN = new InjectionToken('ngx-google-analytics-routing-settings', {
factory: () => ({})
});
/**
* Provide a DI Configuration to attach GA Trigger to Router Events at Angular Startup Cycle.
*/
const NGX_GOOGLE_ANALYTICS_ROUTER_INITIALIZER_PROVIDER = {
provide: APP_BOOTSTRAP_LISTENER,
multi: true,
useFactory: GoogleAnalyticsRouterInitializer,
deps: [
NGX_GOOGLE_ANALYTICS_ROUTING_SETTINGS_TOKEN,
GoogleAnalyticsService
]
};
/**
* Attach a listener to `NavigationEnd` Router event. So, every time Router finish the page resolution it should call `NavigationEnd` event.
* We assume that NavigationEnd is the final page resolution and call GA `page_view` command.
*
* To avoid double binds, we also destroy the subscription when de Bootstrap Component is destroied. But, we don't know for sure
* that this strategy does not cause double bind on multiple bootstrap components.
*
* We are using de component's injector reference to resolve Router, sou I hope there is no problem w/ double bing.
*
* If you have this problem, I encourage not Use NgxGoogleAnalyticsRouterModule and atach the listener on AppComponent initialization.
*/
function GoogleAnalyticsRouterInitializer(settings, gaService) {
return (c) => __awaiter(this, void 0, void 0, function* () {
const router = c.injector.get(Router);
const { include = [], exclude = [] } = settings !== null && settings !== void 0 ? settings : {};
const includeRules = normalizePathRules(include);
const excludeRules = normalizePathRules(exclude);
const subs = router
.events
.pipe(filter((event) => event instanceof NavigationEnd), skip(1), // Prevend double views on the first tigger (because GA Already send one ping on setup)
filter(event => includeRules.length > 0
? includeRules.some(rule => rule.test(event.urlAfterRedirects))
: true), filter(event => excludeRules.length > 0
? !excludeRules.some(rule => rule.test(event.urlAfterRedirects))
: true))
.subscribe(event => gaService.pageView(event.urlAfterRedirects, undefined));
// Cleanup
c.onDestroy(() => subs.unsubscribe());
});
}
/** Converts all path rules from string to Regex instances */
function normalizePathRules(rules) {
return rules.map(rule => (rule instanceof RegExp)
? rule
: new RegExp(`^${rule.replace('*', '.*')}$`, 'i'));
}
/**
* Install Google Analytics Tracking code on your environment and configure tracking ID.
*
* This module should be a dependency on the highest level module of the application, i.e. AppModule in most use cases.
*/
class NgxGoogleAnalyticsModule {
/**
* You should provide a valid Google TrackingCode. This code will be provided to the entire application by
* `NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN` token. You can inject this code in you components if you like by
* use the following injection code `@Inject(NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN) gaConfig: IGoogleAnalyticsSettings`
*
* @param trackingCode The Google Tracking Code
* @param initCommands When placed, it will run any GA Commands in sequence after setup GA environment.
* @param uri When placed, it will change the default js URI to the provided one.
* @param enableTracing When true, trace GA tracking errors on production mode.
* @param nonce When placed, nonce will be added to script tag.
*/
static forRoot(trackingCode, initCommands = [], uri, enableTracing, nonce) {
return {
ngModule: NgxGoogleAnalyticsModule,
providers: [
{
provide: NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN,
useValue: {
trackingCode,
initCommands,
uri,
enableTracing,
nonce
}
},
NGX_GOOGLE_ANALYTICS_INITIALIZER_PROVIDER,
]
};
}
}
NgxGoogleAnalyticsModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: NgxGoogleAnalyticsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
NgxGoogleAnalyticsModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.2", ngImport: i0, type: NgxGoogleAnalyticsModule, declarations: [GaEventDirective,
GaEventCategoryDirective,
GaEventFormInputDirective], exports: [GaEventDirective,
GaEventCategoryDirective,
GaEventFormInputDirective] });
NgxGoogleAnalyticsModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: NgxGoogleAnalyticsModule });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: NgxGoogleAnalyticsModule, decorators: [{
type: NgModule,
args: [{
imports: [],
declarations: [
GaEventDirective,
GaEventCategoryDirective,
GaEventFormInputDirective
],
exports: [
GaEventDirective,
GaEventCategoryDirective,
GaEventFormInputDirective
]
}]
}] });
/**
* Attach a listener to `NavigationEnd` Router event. So, every time Router finish the page resolution it should call `NavigationEnd` event.
* We assume that NavigationEnd is the final page resolution and call GA `page_view` command.
*
* To avoid double binds, we also destroy the subscription when de Bootstrap Component is destroied. But, we don't know for sure
* that this strategy does not cause double bind on multiple bootstrap components.
*
* We are using de component's injector reference to resolve Router, sou I hope there is no problem w/ double bing.
*
* If you have this problem, I encourage not Use NgxGoogleAnalyticsRouterModule and atach the listener on AppComponent initialization.
*
* This Module is just a sugar for:
*
```typescript
constructor(private router: Router) {}
...
ngOnInit() {
...
this.router
.events
.pipe(takeUntil(this.onDestroy$))
.subscribe(event => {
if (event instanceof NavigationEnd) {
gaService.pageView(event.urlAfterRedirects, undefined);
}
});
```
*/
class NgxGoogleAnalyticsRouterModule {
static forRoot(settings) {
return {
ngModule: NgxGoogleAnalyticsRouterModule,
providers: [
{
provide: NGX_GOOGLE_ANALYTICS_ROUTING_SETTINGS_TOKEN,
useValue: settings !== null && settings !== void 0 ? settings : {}
}
]
};
}
}
NgxGoogleAnalyticsRouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: NgxGoogleAnalyticsRouterModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
NgxGoogleAnalyticsRouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.2", ngImport: i0, type: NgxGoogleAnalyticsRouterModule, imports: [CommonModule,
NgxGoogleAnalyticsModule] });
NgxGoogleAnalyticsRouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: NgxGoogleAnalyticsRouterModule, providers: [
NGX_GOOGLE_ANALYTICS_ROUTER_INITIALIZER_PROVIDER
], imports: [CommonModule,
NgxGoogleAnalyticsModule] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: NgxGoogleAnalyticsRouterModule, decorators: [{
type: NgModule,
args: [{
imports: [
CommonModule,
NgxGoogleAnalyticsModule
],
providers: [
NGX_GOOGLE_ANALYTICS_ROUTER_INITIALIZER_PROVIDER
],
declarations: []
}]
}] });
/*
* Public API Surface of ngx-google-analytics
*/
/**
* Generated bundle index. Do not edit.
*/
export { GaActionEnum, GaEventCategoryDirective, GaEventDirective, GaEventFormInputDirective, GoogleAnalyticsInitializer, GoogleAnalyticsRouterInitializer, GoogleAnalyticsService, NGX_DATA_LAYER, NGX_GOOGLE_ANALYTICS_INITIALIZER_PROVIDER, NGX_GOOGLE_ANALYTICS_ROUTER_INITIALIZER_PROVIDER, NGX_GOOGLE_ANALYTICS_ROUTING_SETTINGS_TOKEN, NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN, NGX_GTAG_FN, NGX_WINDOW, NgxGoogleAnalyticsModule, NgxGoogleAnalyticsRouterModule, getDataLayerFn, getGtagFn };
//# sourceMappingURL=ngx-google-analytics.mjs.map