ngx-matomo
Version:
Matomo (aka. Piwik) web analytics for Angular applications.
2,056 lines • 70.9 kB
JavaScript
import * as i0 from '@angular/core';
import { InjectionToken, Injectable, Inject, Directive, Input, HostListener, PLATFORM_ID, NgModule } from '@angular/core';
import * as i2 from '@angular/router';
import { NavigationStart, NavigationEnd } from '@angular/router';
import { filter, map, pairwise } from 'rxjs/operators';
import { isPlatformBrowser } from '@angular/common';
function sanitizeConfiguration(configuration) {
const sanitizedConfiguration = {
...defaultConfiguration,
...configuration,
};
if (configuration.trackAppStart !== undefined && configuration.trackAppStart !== null) {
sanitizedConfiguration.skipTrackingInitialPageView = !configuration.trackAppStart;
}
if (configuration.routeTracking !== undefined && configuration.routeTracking !== null) {
sanitizedConfiguration.routeTracking = configuration.routeTracking;
}
return sanitizedConfiguration;
}
/**
* Injection token for Matomo configuration.
*/
const MATOMO_CONFIGURATION = new InjectionToken('MATOMO_CONFIGURATION');
/**
* Default configuration for the Matomo module.
*/
const defaultConfiguration = {
scriptVersion: 4,
trackers: [],
requireConsent: false,
requireCookieConsent: false,
skipTrackingInitialPageView: false,
trackLinks: true,
trackLinkValue: false,
routeTracking: {
enable: false,
},
};
/**
* Service for injecting the Matomo tracker in the application.
* This service shall no longer be used directly within an application.
*/
class MatomoInjector {
/**
* Creates an instance of MatomoInjector.
*
* @param configuration Matomo configuration provided by DI.
*/
constructor(configuration) {
this.configuration = configuration;
try {
window['_paq'] = window['_paq'] || (!!this.configuration.scriptUrl ? [] : { push: () => { } });
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Configures and injects the Matomo tracker in the DOM.
*/
init() {
try {
if (this.configuration?.requireConsent === true) {
window['_paq'].push(['requireConsent']);
}
else if (this.configuration?.requireCookieConsent === true) {
window['_paq'].push(['requireCookieConsent']);
}
if (this.configuration?.skipTrackingInitialPageView === false) {
window['_paq'].push(['trackPageView']);
if (this.configuration?.trackLinks === true &&
this.configuration?.routeTracking?.enable === false) {
setTimeout(() => {
window['_paq'].push([
'enableLinkTracking',
this.configuration?.trackLinkValue ?? false,
]);
}, 0);
}
}
if (this.configuration.trackers?.length) {
const [mainTracker, ...otherTrackers] = this.configuration.trackers;
window['_paq'].push(['setTrackerUrl', mainTracker.trackerUrl]);
window['_paq'].push(['setSiteId', mainTracker.siteId.toString()]);
otherTrackers.forEach((tracker) => window['_paq'].push(['addTracker', tracker.trackerUrl, tracker.siteId.toString()]));
}
if (!!this.configuration.scriptUrl) {
const script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.defer = true;
script.src = this.configuration.scriptUrl;
const firstScript = document.getElementsByTagName('script')[0];
firstScript.parentNode?.insertBefore(script, firstScript);
}
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: MatomoInjector, deps: [{ token: MATOMO_CONFIGURATION }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: MatomoInjector }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: MatomoInjector, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Inject,
args: [MATOMO_CONFIGURATION]
}] }]; } });
/**
* Wrapper for functions available in the Matomo Javascript tracker.
*
* @export
*/
class MatomoTracker {
/**
* Creates an instance of MatomoTracker.
*
* @param configuration Matomo configuration provided by DI.
*/
constructor(configuration) {
this.configuration = configuration;
try {
if (typeof window['_paq'] === 'undefined') {
console.warn('Matomo has not yet been initialized!');
}
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Logs a visit to this page.
*
* @param [customTitle] Optional title of the visited page.
*/
trackPageView(customTitle) {
try {
const args = [];
if (!!customTitle) {
args.push(customTitle);
}
window['_paq'].push(['trackPageView', ...args]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Logs an event with an event category (Videos, Music, Games…), an event action (Play, Pause, Duration,
* Add Playlist, Downloaded, Clicked…), and an optional event name and optional numeric value.
*
* @param category Category of the event.
* @param action Action of the event.
* @param [name] Optional name of the event.
* @param [value] Optional value for the event.
*/
trackEvent(category, action, name, value) {
try {
const args = [category, action];
if (!!name) {
args.push(name);
if (typeof value === 'number') {
args.push(value);
}
}
window['_paq'].push(['trackEvent', ...args]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Logs an internal site search for a specific keyword, in an optional category,
* specifying the optional count of search results in the page.
*
* @param keyword Keywords of the search query.
* @param [category] Optional category of the search query.
* @param [resultsCount] Optional number of results returned by the search query.
*/
trackSiteSearch(keyword, category, resultsCount) {
try {
const args = [keyword];
if (!!category) {
args.push(category);
if (typeof resultsCount === 'number') {
args.push(resultsCount);
}
}
window['_paq'].push(['trackSiteSearch', ...args]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Manually logs a conversion for the numeric goal ID, with an optional numeric custom revenue customRevenue.
*
* @param idGoal numeric ID of the goal to log a conversion for.
* @param [customRevenue] Optional custom revenue to log for the goal.
*/
trackGoal(idGoal, customRevenue) {
try {
const args = [idGoal];
if (typeof customRevenue === 'number') {
args.push(customRevenue);
}
window['_paq'].push(['trackGoal', ...args]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Manually logs a click from your own code.
*
* @param url Full URL which is to be tracked as a click.
* @param linkType Either 'link' for an outlink or 'download' for a download.
*/
trackLink(url, linkType) {
try {
window['_paq'].push(['trackLink', url, linkType]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Scans the entire DOM for all content blocks and tracks all impressions once the DOM ready event has been triggered.
*
* @see {@link https://developer.matomo.org/guides/content-tracking|Content Tracking}
*/
trackAllContentImpressions() {
try {
window['_paq'].push(['trackAllContentImpressions']);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Scans the entire DOM for all content blocks as soon as the page is loaded.<br />
* It tracks an impression only if a content block is actually visible.
*
* @param checkOnScroll If true, checks for new content blocks while scrolling the page.
* @param timeInterval Duration, in milliseconds, between two checks upon scroll.
* @see {@link https://developer.matomo.org/guides/content-tracking|Content Tracking}
*/
trackVisibleContentImpressions(checkOnScroll, timeInterval) {
try {
window['_paq'].push(['trackVisibleContentImpressions', checkOnScroll, timeInterval]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Scans the given DOM node and its children for content blocks and tracks an impression for them
* if no impression was already tracked for it.
*
* @param node DOM node in which to look for content blocks which have not been previously tracked.
* @see {@link https://developer.matomo.org/guides/content-tracking|Content Tracking}
*/
trackContentImpressionsWithinNode(node) {
try {
window['_paq'].push(['trackContentImpressionsWithinNode', node]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Tracks an interaction with the given DOM node/content block.
*
* @param node DOM node for which to track a content interaction.
* @param contentInteraction Name of the content interaction.
* @see {@link https://developer.matomo.org/guides/content-tracking|Content Tracking}
*/
trackContentInteractionNode(node, contentInteraction) {
try {
window['_paq'].push(['trackContentInteractionNode', node, contentInteraction]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Tracks a content impression using the specified values.
*
* @param contentName Content name.
* @param contentPiece Content piece.
* @param contentTarget Content target.
* @see {@link https://developer.matomo.org/guides/content-tracking|Content Tracking}
*/
trackContentImpression(contentName, contentPiece, contentTarget) {
try {
window['_paq'].push(['trackContentImpression', contentName, contentPiece, contentTarget]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Tracks a content interaction using the specified values.
*
* @param contentInteraction Content interaction.
* @param contentName Content name.
* @param contentPiece Content piece.
* @param contentTarget Content target.
* @see {@link https://developer.matomo.org/guides/content-tracking|Content Tracking}
*/
trackContentInteraction(contentInteraction, contentName, contentPiece, contentTarget) {
try {
window['_paq'].push([
'trackContentInteraction',
contentInteraction,
contentName,
contentPiece,
contentTarget,
]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Logs all found content blocks within a page to the console.<br />
* This is useful to debug / test content tracking.
*/
logAllContentBlocksOnPage() {
try {
window['_paq'].push(['logAllContentBlocksOnPage']);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sends a ping request.<br />
* Ping requests do not track new actions.
* If they are sent within the standard visit length, they will extend the existing visit and the current last action for the visit.
* If sent after the standard visit length, ping requests will create a new visit using the last action in the last known visit.<br />
* See also enableHeartBeatTimer.
*/
ping() {
try {
window['_paq'].push(['ping']);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Installs a Heart beat timer that will regularly send requests to Matomo in order to better measure the time spent on the page.<br />
* These requests will be sent only when the user is actively viewing the page (when the tab is active and in focus).<br />
* These requests will not track additional actions or page views.<br />
* By default, the delay is set to 15 seconds.
*
* @param delay Delay, in seconds, between two heart beats to the server.
*/
enableHeartBeatTimer(delay) {
try {
window['_paq'].push(['enableHeartBeatTimer', delay]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Installs link tracking on all applicable link elements.
*
* @param [enable=false] Set to true to use pseudo click-handler (treat middle click and open contextmenu as
* left click).<br />
* A right click (or any click that opens the context menu) on a link will be tracked as clicked even if "Open in new tab"
* is not selected.<br />
* If false (default), nothing will be tracked on open context menu or middle click.
*/
enableLinkTracking(enable = false) {
try {
window['_paq'].push(['enableLinkTracking', enable]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Enables cross domain linking. By default, the visitor ID that identifies a unique visitor is stored in the browser's
* first party cookies.<br />
* This means the cookie can only be accessed by pages on the same domain.<br />
* If you own multiple domains and would like to track all the actions and pageviews of a specific visitor into the same visit,
* you may enable cross domain linking.<br />
* Whenever a user clicks on a link it will append a URL parameter pk_vid to the clicked URL which forwards the current
* visitor ID value to the page of the different domain.
*
* @see {@link https://matomo.org/faq/how-to/faq_23654/|Cross Domain Linking}
*/
enableCrossDomainLinking() {
try {
window['_paq'].push(['enableCrossDomainLinking']);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets the cross domain linking timeout.<br />
* By default, the two visits across domains will be linked together when the link is clicked and the page is loaded within
* a 180 seconds timeout window.
*
* @param timeout Timeout, in seconds, between two actions across two domains before creating a new visit.
* @see {@link https://matomo.org/faq/how-to/faq_23654/|Cross Domain Linking}
*/
setCrossDomainLinkingTimeout(timeout) {
try {
window['_paq'].push(['setCrossDomainLinkingTimeout', timeout]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Returns the query parameter to append to links to handle cross domain linking.<br />
* Use this to add cross domain support for links that are added to the DOM dynamically.
*
* @returns Promise for the `pk_vid` query parameter.
* @see {@link https://matomo.org/faq/how-to/faq_23654/|Cross Domain Linking}
*/
getCrossDomainLinkingUrlParameter() {
return new Promise((resolve, reject) => {
try {
window['_paq'].push([
function () {
resolve(this.getCrossDomainLinkingUrlParameter());
},
]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
reject(e);
}
}
});
}
/**
* Overrides document.title
*
* @param title Title of the document.
*/
setDocumentTitle(title) {
try {
window['_paq'].push(['setDocumentTitle', title]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets array of hostnames or domains to be treated as local.<br />
* For wildcard subdomains, you can use: `setDomains('.example.com')`; or `setDomains('*.example.com');`.<br />
* You can also specify a path along a domain: `setDomains('*.example.com/subsite1');`.
*
* @param domains List of hostnames or domains, with or without path, to be treated as local.
* @see {@link https://matomo.org/faq/how-to/faq_23654/|Cross Domain Linking}
*/
setDomains(domains) {
try {
window['_paq'].push(['setDomains', domains]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Override the page's reported URL.
*
* @param url URL to be reported for the page.
*/
setCustomUrl(url) {
try {
window['_paq'].push(['setCustomUrl', url]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Overrides the detected Http-Referer.
*
* @param url URL to be reported for the referer.
*/
setReferrerUrl(url) {
try {
window['_paq'].push(['setReferrerUrl', url]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Specifies the website ID.<br />
* Redundant: can be specified in getTracker() constructor.
*
* // TODO Investigate if setSiteId needs to be removed from MatomoTracker.
* @param siteId Site ID for the tracker.
*/
setSiteId(siteId) {
try {
window['_paq'].push(['setSiteId', siteId]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Specifies the Matomo HTTP API URL endpoint.<br />
* Points to the root directory of Matomo, e.g. http://matomo.example.org/ or https://example.org/matomo/.<br />
* This function is only useful when the 'Overlay' report is not working.<br />
* By default, you do not need to use this function.
*
* @param url URL for Matomo HTTP API endpoint.
*/
setApiUrl(url) {
try {
window['_paq'].push(['setApiUrl', url]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Specifies the Matomo server URL.<br />
* Redundant: can be specified in getTracker() constructor.
*
* // TODO Investigate if setTrackerUrl needs to be removed from MatomoTracker.
* @param url URL for the Matomo server.
*/
setTrackerUrl(url) {
try {
window['_paq'].push(['setTrackerUrl', url]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Returns the Matomo server URL.
*
* @returns Promise for the Matomo server URL.
*/
getMatomoUrl() {
return new Promise((resolve, reject) => {
try {
window['_paq'].push([
function () {
resolve(this.getPiwikUrl());
},
]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
reject(e);
}
}
});
}
/**
* Returns the current url of the page that is currently being visited.<br />
* If a custom URL was set before calling this method, the custom URL will be returned.
*
* @returns Promise for the URL of the current page.
*/
getCurrentUrl() {
return new Promise((resolve, reject) => {
try {
window['_paq'].push([
function () {
resolve(this.getCurrentUrl());
},
]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
reject(e);
}
}
});
}
/**
* Sets classes to be treated as downloads (in addition to piwik_download).
*
* @param classes Class, or list of classes to be treated as downloads.
*/
setDownloadClasses(classes) {
try {
window['_paq'].push(['setDownloadClasses', classes]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets file extensions to be recognized as downloads.<br />
* Example: `'docx'` or `['docx', 'xlsx']`.
*
* @param extensions Extension, or list of extensions to be recognized as downloads.
*/
setDownloadExtensions(extensions) {
try {
window['_paq'].push(['setDownloadClasses', extensions]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets additional file extensions to be recognized as downloads.<br />
* Example: `'docx'` or `['docx', 'xlsx']`.
*
* @param extensions Extension, or list of extensions to be recognized as downloads.
*/
addDownloadExtensions(extensions) {
try {
window['_paq'].push(['setDownloadClasses', extensions]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Specifies file extensions to be removed from the list of download file extensions.<br />
* Example: `'docx'` or `['docx', 'xlsx']`.
*
* @param extensions Extension, or list of extensions not to be recognized as downloads.
*/
removeDownloadExtensions(extensions) {
try {
window['_paq'].push(['setDownloadClasses', extensions]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets classes to be ignored if present in link (in addition to piwik_ignore).
*
* @param classes Class, or list of classes to be ignored if present in link.
*/
setIgnoreClasses(classes) {
try {
window['_paq'].push(['setDownloadClasses', classes]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets classes to be treated as outlinks (in addition to piwik_link).
*
* @param classes Class, or list of classes to be treated as outlinks.
*/
setLinkClasses(classes) {
try {
window['_paq'].push(['setDownloadClasses', classes]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets delay for link tracking (in milliseconds).
*
* @param delay Delay, in milliseconds, for link tracking.
*/
setLinkTrackingTimer(delay) {
try {
window['_paq'].push(['setLinkTrackingTimer', delay]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Returns delay for link tracking.
*
* @returns Promise for the delay in milliseconds.
*/
getLinkTrackingTimer() {
return new Promise((resolve, reject) => {
try {
window['_paq'].push([
function () {
resolve(this.getLinkTrackingTimer());
},
]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
reject(e);
}
}
});
}
/**
* Sets if or not to record the hash tag (anchor) portion of URLs.
*
* @param value If true, the hash tag portion of the URLs won't be recorded.
*/
discardHashTag(value) {
try {
window['_paq'].push(['discardHashTag', value]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* By default Matomo uses the browser DOM Timing API to accurately determine the time it takes to generate and download
* the page. You may overwrite this value with this function.
* This function is deprecated in Matomo 4.x.
*
* @param generationTime Time, in milliseconds, of the page generation.
*/
setGenerationTimeMs(generationTime) {
if (this.configuration.scriptVersion < 4) {
try {
window['_paq'].push(['setGenerationTimeMs', generationTime]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
}
/**
* Appends a custom string to the end of the HTTP request to piwik.php.
*
* @param appendToUrl String to append to the end of the HTTP request to piwik.php/matomo.php.
*/
appendToTrackingUrl(appendToUrl) {
try {
window['_paq'].push(['appendToTrackingUrl', appendToUrl]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Enables a frame-buster to prevent the tracked web page from being framed/iframed.
*/
killFrame() {
try {
window['_paq'].push(['killFrame']);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Forces the browser to load the live URL if the tracked web page is loaded from a local file
* (e.g., saved to someone's desktop).
*
* @param url URL to track instead of file:// URLs.
*/
redirectFile(url) {
try {
window['_paq'].push(['redirectFile', url]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Records how long the page has been viewed if the minimumVisitLength is attained;
* the heartBeatDelay determines how frequently to update the server.
*
* @param minimumVisitLength Duration before notifying the server for the duration of the visit to a page.
* @param heartBeatDelay Delay, in seconds, between two updates to the server.
* @see {@link https://developer.matomo.org/guides/tracking-javascript-guide#accurately-measure-the-time-spent-on-each-page}
*/
setHeartBeatTimer(minimumVisitLength, heartBeatDelay) {
try {
window['_paq'].push(['setHeartBeatTimer', minimumVisitLength, heartBeatDelay]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Returns the 16 characters ID for the visitor.
*
* @returns Promise for the the 16 characters ID for the visitor.
*/
getVisitorId() {
return new Promise((resolve, reject) => {
try {
window['_paq'].push([
function () {
resolve(this.getVisitorId());
},
]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
reject(e);
}
}
});
}
/**
* Returns the visitor cookie contents in an array.
*
* @returns Promise for the cookie contents in an array.
*/
getVisitorInfo() {
return new Promise((resolve, reject) => {
try {
window['_paq'].push([
function () {
resolve(this.getVisitorInfo());
},
]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
reject(e);
}
}
});
}
/**
* Returns the visitor attribution array (Referer information and/or Campaign name & keyword).<br />
* Attribution information is used by Matomo to credit the correct referrer (first or last referrer)
* used when a user triggers a goal conversion.
*
* @returns Promise for the visitor attribution array (Referer information and/or Campaign name & keyword).
*/
getAttributionInfo() {
return new Promise((resolve, reject) => {
try {
window['_paq'].push([
function () {
resolve(this.getAttributionInfo());
},
]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
reject(e);
}
}
});
}
/**
* Returns the attribution campaign name.
*
* @returns Promise for the the attribution campaign name.
*/
getAttributionCampaignName() {
return new Promise((resolve, reject) => {
try {
window['_paq'].push([
function () {
resolve(this.getAttributionCampaignName());
},
]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
reject(e);
}
}
});
}
/**
* Returns the attribution campaign keyword.
*
* @returns Promise for the attribution campaign keyword.
*/
getAttributionCampaignKeyword() {
return new Promise((resolve, reject) => {
try {
window['_paq'].push([
function () {
resolve(this.getAttributionCampaignKeyword());
},
]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
reject(e);
}
}
});
}
/**
* Returns the attribution referrer timestamp.
*
* @returns Promise for the attribution referrer timestamp (as string).
*/
getAttributionReferrerTimestamp() {
return new Promise((resolve, reject) => {
try {
window['_paq'].push([
function () {
resolve(this.getAttributionReferrerTimestamp());
},
]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
reject(e);
}
}
});
}
/**
* Returns the attribution referrer URL.
*
* @returns Promise for the attribution referrer URL
*/
getAttributionReferrerUrl() {
return new Promise((resolve, reject) => {
try {
window['_paq'].push([
function () {
resolve(this.getAttributionReferrerUrl());
},
]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
reject(e);
}
}
});
}
/**
* Returns the User ID string if it was set.
*
* @returns Promise for the User ID for the visitor.
* @see {@link https://matomo.org/docs/user-id/|Matomo User ID}
*/
getUserId() {
return new Promise((resolve, reject) => {
try {
window['_paq'].push([
function () {
resolve(this.getUserId());
},
]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
reject(e);
}
}
});
}
/**
* Sets a User ID to this user (such as an email address or a username).
*
* @param userId User ID to set for the current visitor.
* @see {@link https://matomo.org/docs/user-id/|Matomo User ID}
*/
setUserId(userId) {
try {
window['_paq'].push(['setUserId', userId]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Resets the User ID which also generates a new Visitor ID.
*
* @see {@link https://matomo.org/docs/user-id/|Matomo User ID}
*/
resetUserId() {
try {
window['_paq'].push(['resetUserId']);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets a custom variable.
*
* @param index Index, the number from 1 to 5 where this custom variable name is stored for the current page view.
* @param name Name, the name of the variable, for example: Category, Sub-category, UserType.
* @param value Value, for example: "Sports", "News", "World", "Business"…
* @param scope Scope of the custom variable:<br />
* - 'page' means the custom variable applies to the current page view.
* - 'visit' means the custom variable applies to the current visitor.
* - 'event' means the custom variable applies to the current event.
* @see {@link https://matomo.org/docs/custom-variables/|Custom Variables}
*/
setCustomVariable(index, name, value, scope) {
try {
window['_paq'].push(['setCustomVariable', index, name, value, scope]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Deletes a custom variable.
*
* @param index Index of the custom variable to delete.
* @param scope Scope of the custom variable to delete.
* @see {@link https://matomo.org/docs/custom-variables/|Custom Variables}
*/
deleteCustomVariable(index, scope) {
try {
window['_paq'].push(['deleteCustomVariable', index, scope]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Deletes all custom variables.
*
* @param scope Scope of the custom variables to delete.
* @see {@link https://matomo.org/docs/custom-variables/|Custom Variables}
*/
deleteCustomVariables(scope) {
try {
window['_paq'].push(['deleteCustomVariables', scope]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Retrieves a custom variable.
*
* @param index Index of the custom variable to retrieve.
* @param scope Scope of the custom variable to retrieve.
* @returns Promise for the value of custom variable.
* @see {@link https://matomo.org/docs/custom-variables/|Custom Variables}
*/
getCustomVariable(index, scope) {
return new Promise((resolve, reject) => {
try {
window['_paq'].push([
function () {
resolve(this.getCustomVariable(index, scope));
},
]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
reject(e);
}
}
});
}
/**
* When called then the Custom Variables of scope 'visit' will be stored (persisted) in a first party cookie
* for the duration of the visit.<br />
* This is useful if you want to call getCustomVariable later in the visit.<br />
* (by default custom variables are not stored on the visitor's computer.)
*
* @see {@link https://matomo.org/docs/custom-variables/|Custom Variables}
*/
storeCustomVariablesInCookie() {
try {
window['_paq'].push(['storeCustomVariablesInCookie']);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets a custom dimension.<br />
* (requires Matomo 2.15.1 + Custom Dimensions plugin)
*
* @param customDimensionId ID of the custom dimension to set.
* @param customDimensionValue Value to be set.
* @see {@link https://plugins.piwik.org/CustomDimensions|Custom Dimensions}
*/
setCustomDimension(customDimensionId, customDimensionValue) {
try {
window['_paq'].push(['setCustomDimension', customDimensionId, customDimensionValue]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Deletes a custom dimension.<br />
* (requires Matomo 2.15.1 + Custom Dimensions plugin)
*
* @param customDimensionId ID of the custom dimension to delete.
* @see {@link https://plugins.piwik.org/CustomDimensions|Custom Dimensions}
*/
deleteCustomDimension(customDimensionId) {
try {
window['_paq'].push(['deleteCustomDimension', customDimensionId]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Retrieve a custom dimension.<br />
* (requires Matomo 2.15.1 + Custom Dimensions plugin)
*
* @param customDimensionId ID of the custom dimension to retrieve.
* @returns Promise for the value for the requested custom dimension.
* @see {@link https://plugins.piwik.org/CustomDimensions|Custom Dimensions}
*/
getCustomDimension(customDimensionId) {
return new Promise((resolve, reject) => {
try {
window['_paq'].push([
function () {
resolve(this.getCustomDimension(customDimensionId));
},
]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
reject(e);
}
}
});
}
/**
* Sets campaign name parameter(s).
*
* @param name Name of the campaign
* @see {@link https://matomo.org/docs/tracking-campaigns/|Campaigns}
*/
setCampaignNameKey(name) {
try {
window['_paq'].push(['setCampaignNameKey', name]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets campaign keyword parameter(s).
*
* @param keyword Keyword parameter(s) of the campaign.
* @see {@link https://matomo.org/docs/tracking-campaigns/|Campaigns}
*/
setCampaignKeywordKey(keyword) {
try {
window['_paq'].push(['setCampaignKeywordKey', keyword]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets if or not to attribute a conversion to the first referrer.<br />
* By default, conversion is attributed to the most recent referrer.
*
* @param conversionToFirstReferrer If true, Matomo will attribute the Goal conversion to the first referrer used
* instead of the last one.
* @see {@link https://matomo.org/docs/tracking-campaigns/|Campaigns}
* @see {@link https://matomo.org/faq/general/faq_106/#faq_106|Conversions to the first referrer}
*/
setConversionAttributionFirstReferrer(conversionToFirstReferrer) {
try {
window['_paq'].push(['setConversionAttributionFirstReferrer', conversionToFirstReferrer]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets the current page view as a product or category page view.<br />
* When you call setEcommerceView, it must be followed by a call to trackPageView to record the product or category page view.
*
* @param productSKU SKU of the viewed product.
* @param productName Name of the viewed product.
* @param productCategory Category of the viewed product.
* @param price Price of the viewed product.
*/
setEcommerceView(productSKU, productName, productCategory, price) {
try {
window['_paq'].push(['setEcommerceView', productSKU, productName, productCategory, price]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Adds a product into the eCommerce order.<br />
* Must be called for each product in the order.
*
* @param productSKU SKU of the product to add.
* @param [productName] Optional name of the product to add.
* @param [productCategory] Optional category of the product to add.
* @param [price] Optional price of the product to add.
* @param [quantity] Optional quantity of the product to add.
*/
addEcommerceItem(productSKU, productName, productCategory, price, quantity) {
try {
const args = [productSKU];
if (!!productName) {
args.push(productName);
if (!!productCategory) {
args.push(productCategory);
if (typeof price === 'number') {
args.push(price);
if (typeof quantity === 'number') {
args.push(quantity);
}
}
}
}
window['_paq'].push(['addEcommerceItem', ...args]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Removes the specified product from the untracked ecommerce order.
*
* @param productSKU SKU of the product to remove.
*/
removeEcommerceItem(productSKU) {
try {
const args = [productSKU];
window['_paq'].push(['removeEcommerceItem', ...args]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Removes all products in the untracked ecommerce order.<br />
* Note: this is done automatically after trackEcommerceOrder() is called.
*/
clearEcommerceCart() {
try {
window['_paq'].push(['clearEcommerceCart']);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Returns all ecommerce items currently in the untracked ecommerce order.
* The returned array will be a copy, so changing it won't affect the ecommerce order.<br />
* To affect what gets tracked, use the addEcommerceItem()/removeEcommerceItem()/clearEcommerceCart() methods.<br />
* Use this method to see what will be tracked before you track an order or cart update.
*/
getEcommerceItems() {
return new Promise((resolve, reject) => {
try {
window['_paq'].push([
function () {
resolve(this.getEcommerceItems());
},
]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
reject(e);
}
}
});
}
/**
* Tracks a shopping cart.<br />
* Call this function every time a user is adding, updating or deleting a product from the cart.
*
* @param grandTotal Grand total of the shopping cart.
*/
trackEcommerceCartUpdate(grandTotal) {
try {
window['_paq'].push(['trackEcommerceCartUpdate', grandTotal]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Tracks an Ecommerce order, including any eCommerce item previously added to the order.<br />
* orderId and grandTotal (ie.revenue) are required parameters.
*
* @param orderId ID of the tracked order.
* @param grandTotal Grand total of the tracked order.
* @param [subTotal] Sub total of the tracked order.
* @param [tax] Taxes for the tracked order.
* @param [shipping] Shipping fees for the tracked order.
* @param [discount] Discount granted for the tracked order.
*/
trackEcommerceOrder(orderId, grandTotal, subTotal, tax, shipping, discount) {
try {
const args = [orderId, grandTotal];
if (typeof subTotal === 'number') {
args.push(subTotal);
if (typeof tax === 'number') {
args.push(tax);
if (typeof shipping === 'number') {
args.push(shipping);
if (typeof discount === 'number' || typeof discount === 'boolean') {
args.push(discount);
}
}
}
}
window['_paq'].push(['trackEcommerceOrder', ...args]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* By default the Matomo tracker assumes consent to tracking.
* To change this behavior so nothing is tracked until a user consents, you must call requireConsent.
*/
requireConsent() {
try {
window['_paq'].push(['requireConsent']);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Require user cookie consent before storing and using any cookies.
*/
requireCookieConsent() {
try {
window['_paq'].push(['requireCookieConsent']);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Marks that the current user has consented.<br />
* The consent is one-time only, so in a subsequent browser session, the user will have to consent again.<br />
* To remember consent, see the method below: rememberConsentGiven.
*/
setConsentGiven() {
try {
window['_paq'].push(['setConsentGiven']);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Marks that the current user has consented to store and use cookies.<br />
* The consent is one-time only, so in a subsequent browser session, the user will have to consent again.<br />
* To remember consent, see the method below: rememberCookieConsentGiven.
*/
setCookieConsentGiven() {
try {
window['_paq'].push(['setCookieConsentGiven']);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Marks that the current user has consented, and remembers this consent through a browser cookie.<br />
* The next time the user visits the site, Matomo will remember that they consented, and track them.<br />
* If you call this method, you do not need to call setConsentGiven.
*
* @param hoursToExpire Expiry period for your user consent.
*/
rememberConsentGiven(hoursToExpire) {
try {
const args = [];
if (typeof hoursToExpire === 'number') {
args.push(hoursToExpire);
}
window['_paq'].push(['rememberConsentGiven', ...args]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Marks that the current user has consented, and remembers this consent through a browser cookie.<br />
* The next time the user visits the site, Matomo will remember that they consented, and track them.<br />
* If you call this method, you do not need to call setCookieConsentGiven.
*
* @param hoursToExpire Expiry period for your user consent.
*/
rememberCookieConsentGiven(hoursToExpire) {
try {
const args = [];
if (typeof hoursToExpire === 'number') {
args.push(hoursToExpire);
}
window['_paq'].push(['rememberCookieConsentGiven', ...args]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Removes a user's consent, both if the consent was one-time only and if the consent was remembered.<br />
* This makes sure the cookie that remembered the given consent is deleted.<br />
* After calling this method, the user will have to consent again in order to be tracked.
*/
forgetConsentGiven() {
try {
window['_paq'].push(['forgetConsentGiven']);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Removes a user's consent, both if the consent was one-time only and if the consent was remembered.<br />
* This makes sure the cookie that remembered the given consent is deleted.<br />
* After calling this method, the user will have to consent again in order to be tracked.
*/
forgetCookieConsentGiven() {
try {
window['_paq'].push(['forgetCookieConsentGiven']);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets if to not to track users who opt out of tracking using Mozilla's (proposed) Do Not Track setting.
*
* @param doNotTrack If true, users who opted for Do Not Track in their settings won't be tracked.
* @see {@link https://www.w3.org/TR/tracking-dnt/}
*/
setDoNotTrack(doNotTrack) {
try {
window['_paq'].push(['setDoNotTrack', doNotTrack]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Disables all first party cookies.<br />
* Existing Matomo cookies for this websites will be deleted on the next page view.
*/
disableCookies() {
try {
window['_paq'].push(['disableCookies']);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Deletes the tracking cookies currently set (useful when creating new visits).
*/
deleteCookies() {
try {
window['_paq'].push(['deleteCookies']);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Returns whether cookies are enabled and supported by this browser.
*
* @returns Promise for the support and activation of cookies.
*/
hasCookies() {
return new Promise((resolve, reject) => {
try {
window['_paq'].push([
function () {
resolve(this.hasCookies());
},
]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
reject(e);
}
}
});
}
/**
* Sets the tracking cookie name prefix.<br />
* Default prefix is 'pk'.
*
* @param prefix Prefix for the tracking cookie names.
*/
setCookieNamePrefix(prefix) {
try {
window['_paq'].push(['setCookieNamePrefix', prefix]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets the domain of the tracking cookies.<br />
* Default is the document domain.<br />
* If your website can be visited at both www.example.com and example.com, you would use: `'.example.com'` or `'*.example.com'`.
*
* @param domain Domain of the tracking cookies.
*/
setCookieDomain(domain) {
try {
window['_paq'].push(['setCookieDomain', domain]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets the path of the tracking cookies.<br />
* Default is '/'.
*
* @param path Path of the tracking cookies.
*/
setCookiePath(path) {
try {
window['_paq'].push(['setCookiePath', path]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets if or not to enable the Secure cookie flag on all first party cookies.<br />
* This should be used when your website is only available under HTTPS so that all tracking cookies are always sent
* over secure connection.
*
* @param secure If true, the secure cookie flag will be set on all first party cookies.
*/
setSecureCookie(secure) {
try {
window['_paq'].push(['setSecureCookie', secure]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets the visitor cookie timeout.<br />
* Default is 13 months.
*
* @param timeout Timeout, in seconds, for the visitor cookie timeout.
*/
setVisitorCookieTimeout(timeout) {
try {
window['_paq'].push(['setVisitorCookieTimeout', timeout]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets the referral cookie timeout.<br />
* Default is 6 months.
*
* @param timeout Timeout, in seconds, for the referral cookie timeout.
*/
setReferralCookieTimeout(timeout) {
try {
window['_paq'].push(['setReferralCookieTimeout', timeout]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets the session cookie timeout.<br />
* Default is 30 minutes.
*
* @param timeout Timeout, in seconds, for the session cookie timeout.
*/
setSessionCookieTimeout(timeout) {
try {
window['_paq'].push(['setSessionCookieTimeout', timeout]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Adds a click listener to a specific link element.<br />
* When clicked, Matomo will log the click automatically.
*
* @param element Element on which to add a click listener.
*/
addListener(element) {
try {
window['_paq'].push(['addListener', element]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets the request method to either 'GET' or 'POST'. (The default is 'GET'.)<br />
* To use the POST request method, either:<br />
* 1) the Matomo host is the same as the tracked website host (Matomo installed in the same domain as your tracked website), or<br />
* 2) if Matomo is not installed on the same host as your website, you need to enable CORS (Cross domain requests).
*
* @param method HTTP method for sending information to the Matomo server.
*/
setRequestMethod(method) {
try {
window['_paq'].push(['setRequestMethod', method]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets a function that will process the request content.<br />
* The function will be called once the request (query parameters string) has been prepared, and before the request content is sent.
*
* @param callback Function that will process the request content.
*/
setCustomRequestProcessing(callback) {
try {
window['_paq'].push(['setCustomRequestProcessing', callback]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Sets request Content-Type header value.<br />
* Applicable when 'POST' request method is used via setRequestMethod.
*
* @param contentType Value for Content-Type HTTP header.
*/
setRequestContentType(contentType) {
try {
window['_paq'].push(['setRequestContentType', contentType]);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
/**
* Disables the feature which groups together multiple tracking requests and send them as a bulk POST request.<br />
* Disabling this feature is useful when you want to be able to replay all logs: one must use disableQueueRequest
* to disable this behavior to later be able to replay logged Matomo logs (otherwise a subset of the requests
* wouldn't be able to be replayed).
*/
disableQueueRequest() {
try {
window['_paq'].push(['disableQueueRequest']);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: MatomoTracker, deps: [{ token: MATOMO_CONFIGURATION }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: MatomoTracker }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: MatomoTracker, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Inject,
args: [MATOMO_CONFIGURATION]
}] }]; } });
/**
* Type guard for checking if a value or object is non null.
*
* @export
*/
function isNonNull(value) {
return value != null;
}
/**
* Type guard for checking if a value or object is defined.
*
* @export
*/
function isDefined(value) {
return value !== undefined && value !== null;
}
/**
* Checks if a value or object is non null or undefined, throws an error otherwise.
*
* @export
*/
function requireNonNull(value, message) {
if (value === null || value === undefined) {
throw new Error('Unexpected ' + value + ' value: ' + message);
}
return value;
}
/**
* Service for tracking route changes.
*
* @export
*/
class MatomoRouteTracker {
/**
* Creates an instance of MatomoRouteTracker.
*
* @param configuration Matomo configuration provided by DI.
* @param matomoTracker Instance of MatomoTracker provided by DI.
* @param router Instance of Router provided by DI.
* @param activatedRoute Instance of ActivatedRoute provided by DI.
*/
constructor(configuration, matomoTracker, router, activatedRoute) {
this.configuration = configuration;
this.matomoTracker = matomoTracker;
this.router = router;
this.activatedRoute = activatedRoute;
}
/**
* Starts tracking route changes.
* Matomo DocumentTitle will be set with `data.matomoTitle` of your routes.
*
* This service shall not be used directly within an application.
*/
startTracking() {
this.subscription = this.router.events
.pipe(filter((event) => event instanceof NavigationStart || event instanceof NavigationEnd), map((event) => ({ timestamp: new Date().getTime(), event })), pairwise(), filter(([a, b]) => a.event instanceof NavigationStart && b.event instanceof NavigationEnd))
.subscribe({
next: ([start, end]) => {
let currentRoute = this.activatedRoute.root;
while (currentRoute.firstChild) {
currentRoute = currentRoute.firstChild;
}
// Set referrer if it exists
if (this.previousPageUrl) {
this.matomoTracker.setReferrerUrl(this.previousPageUrl);
}
// Track current page
if (!!currentRoute.snapshot.data['matomoTitle'] || !!currentRoute.snapshot.title) {
this.matomoTracker.setDocumentTitle(currentRoute.snapshot.data['matomoTitle'] ?? currentRoute.snapshot.title);
}
this.matomoTracker.setCustomUrl(window.location.href);
// Remove all previously assigned custom variables
// (requires Matomo (formerly Piwik) 3.0.2+)
this.matomoTracker.deleteCustomVariables('page');
this.matomoTracker.setGenerationTimeMs(end.timestamp - start.timestamp);
this.matomoTracker.trackPageView();
// Set previous route URL
this.previousPageUrl = window.location.href;
// Make Matomo aware of newly added content
this.configuration?.routeTracking?.contentIds
?.map(document.getElementById)
?.filter(isNonNull)
?.forEach((content) => {
// TODO To be implemented when Media Analytics will be supported.
// this.matomoTracker.scanForMedia(content);
// TODO To be implemented when Form Analytics will be supported.
// this.matomoTracker.scanForForms(content);
this.matomoTracker.trackContentImpressionsWithinNode(content);
});
if (this.configuration.trackLinks === true) {
this.matomoTracker.enableLinkTracking(this.configuration.trackLinkValue);
}
},
});
}
/**
* Stops tracking route changes.
*/
stopTracking() {
if (!!this.subscription) {
this.subscription.unsubscribe();
this.subscription = undefined;
}
}
/**
* Angular OnDestroy lifecycle hook.
*/
ngOnDestroy() {
this.stopTracking();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: MatomoRouteTracker, deps: [{ token: MATOMO_CONFIGURATION }, { token: MatomoTracker }, { token: i2.Router }, { token: i2.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: MatomoRouteTracker }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: MatomoRouteTracker, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Inject,
args: [MATOMO_CONFIGURATION]
}] }, { type: MatomoTracker }, { type: i2.Router }, { type: i2.ActivatedRoute }]; } });
class MatomoTrackClickDirective {
constructor(tracker) {
this.tracker = tracker;
}
onClick() {
this.tracker.trackEvent(requireNonNull(this.matomoClickCategory, 'matomo category is required'), requireNonNull(this.matomoClickAction, 'matomo action is required'), this.matomoClickName, this.matomoClickValue);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: MatomoTrackClickDirective, deps: [{ token: MatomoTracker }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.3", type: MatomoTrackClickDirective, selector: "[matomoClickCategory][matomoClickAction]", inputs: { matomoClickCategory: "matomoClickCategory", matomoClickAction: "matomoClickAction", matomoClickName: "matomoClickName", matomoClickValue: "matomoClickValue" }, host: { listeners: { "click": "onClick()" } }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: MatomoTrackClickDirective, decorators: [{
type: Directive,
args: [{
selector: '[matomoClickCategory][matomoClickAction]',
}]
}], ctorParameters: function () { return [{ type: MatomoTracker }]; }, propDecorators: { matomoClickCategory: [{
type: Input
}], matomoClickAction: [{
type: Input
}], matomoClickName: [{
type: Input
}], matomoClickValue: [{
type: Input
}], onClick: [{
type: HostListener,
args: ['click']
}] } });
/**
* Angular module encapsulating Matomo features.
*/
class MatomoModule {
/**
* Creates an instance of Matomo module.
*
* @param platformId Angular platform provided by DI.
* @param injector Instance of Angular Injector provided by DI.
* @param configuration Matomo configuration provided by DI.
* @param matomoInjector Instance of MatomoInjector provided by DI.
*/
constructor(platformId, injector, configuration, matomoInjector) {
this.platformId = platformId;
this.injector = injector;
this.configuration = configuration;
this.matomoInjector = matomoInjector;
// Warn if module is not being loaded by a browser.
if (!isPlatformBrowser(this.platformId)) {
console.warn('ngx-Matomo does not support server platform');
}
// Inject the Matomo script and create trackers.
this.matomoInjector.init();
// Enable route tracking if requested.
if (this.configuration?.routeTracking?.enable === true) {
// Using Injector instead of DI in order to allow use in routerless apps.
this.injector.get(MatomoRouteTracker).startTracking();
}
}
/**
* Use this method in your root module to provide the MatomoTracker service.
*/
static forRoot(configuration) {
return {
ngModule: MatomoModule,
providers: [
{
provide: MATOMO_CONFIGURATION,
useValue: configuration,
},
MatomoTracker,
MatomoRouteTracker,
],
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: MatomoModule, deps: [{ token: PLATFORM_ID }, { token: i0.Injector }, { token: MATOMO_CONFIGURATION }, { token: MatomoInjector }], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.1.3", ngImport: i0, type: MatomoModule, declarations: [MatomoTrackClickDirective], exports: [MatomoTrackClickDirective] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: MatomoModule, providers: [MatomoInjector, MatomoTracker, MatomoRouteTracker] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: MatomoModule, decorators: [{
type: NgModule,
args: [{
declarations: [MatomoTrackClickDirective],
imports: [],
exports: [MatomoTrackClickDirective],
providers: [MatomoInjector, MatomoTracker, MatomoRouteTracker],
}]
}], ctorParameters: function () { return [{ type: Object, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }, { type: i0.Injector }, { type: undefined, decorators: [{
type: Inject,
args: [MATOMO_CONFIGURATION]
}] }, { type: MatomoInjector }]; } });
/*
* Public API Surface of ngx-matomo
*/
/**
* Generated bundle index. Do not edit.
*/
export { MATOMO_CONFIGURATION, MatomoInjector, MatomoModule, MatomoRouteTracker, MatomoTrackClickDirective, MatomoTracker };
//# sourceMappingURL=ngx-matomo.mjs.map