ngx-matomo-client
Version:
Matomo (fka. Piwik) client for Angular applications
1,305 lines (1,294 loc) • 88.1 kB
JavaScript
import * as i0 from '@angular/core';
import { InjectionToken, inject, INJECTOR, DOCUMENT, runInInjectionContext, Service, PLATFORM_ID, NgZone, ApplicationInitStatus, DestroyRef, provideEnvironmentInitializer, makeEnvironmentProviders, resource, linkedSignal, input, LOCALE_ID, computed, SecurityContext, ChangeDetectionStrategy, Component, Directive, ElementRef, NgModule } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { Subject, switchMap, EMPTY, merge, fromEvent } from 'rxjs';
import { DomSanitizer } from '@angular/platform-browser';
import { toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';
function coerceErrorHandler(errorOrHandler) {
return typeof errorOrHandler === 'string'
? () => {
throw new Error(errorOrHandler);
}
: errorOrHandler;
}
function runOnce(fn, errorOrHandler) {
const errorHandler = errorOrHandler ? coerceErrorHandler(errorOrHandler) : () => undefined;
let run = false;
return (...args) => {
if (run) {
return errorHandler(...args);
}
run = true;
return fn(...args);
};
}
function appendTrailingSlash(str) {
return str.endsWith('/') ? str : `${str}/`;
}
const createDefaultMatomoScriptElement = (scriptUrl, document) => {
const g = document.createElement('script');
g.type = 'text/javascript';
g.defer = true;
g.async = true;
g.src = scriptUrl;
return g;
};
const MATOMO_SCRIPT_FACTORY = new InjectionToken('MATOMO_SCRIPT_FACTORY', {
providedIn: 'root',
factory: () => createDefaultMatomoScriptElement,
});
function requireNonNull(value, message) {
if (value === null || value === undefined) {
throw new Error('Unexpected ' + value + ' value: ' + message);
}
return value;
}
/** Coerce a data-bound value to a boolean */
function coerceCssSizeBinding(value) {
if (value == null) {
return '';
}
return typeof value === 'string' ? value : `${value}px`;
}
class ScriptInjector {
constructor() {
this.scriptFactory = inject(MATOMO_SCRIPT_FACTORY);
this.injector = inject(INJECTOR);
this.document = inject(DOCUMENT);
}
injectDOMScript(scriptUrl) {
const scriptElement = runInInjectionContext(this.injector, () => this.scriptFactory(scriptUrl, this.document));
const selfScript = requireNonNull(this.document.getElementsByTagName('script')[0], 'no existing script found');
const parent = requireNonNull(selfScript.parentNode, "no script's parent node found");
parent.insertBefore(scriptElement, selfScript);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: ScriptInjector, deps: [], target: i0.ɵɵFactoryTarget.Service }); }
static { this.ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.0", ngImport: i0, type: ScriptInjector, autoProvided: false }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: ScriptInjector, decorators: [{
type: Service,
args: [{ autoProvided: false }]
}] });
const CONFIG_NOT_FOUND = 'No Matomo configuration found! Have you included Matomo module using MatomoModule.forRoot() or provideMatomo()?';
/** Internal marker token to detect that router has been enabled */
const MATOMO_ROUTER_ENABLED = new InjectionToken('MATOMO_ROUTER_ENABLED', {
factory() {
return false;
},
});
/** Injection token for {@link MatomoConfiguration} */
const MATOMO_CONFIGURATION = new InjectionToken('MATOMO_CONFIGURATION');
/**
* For internal use only. Injection token for {@link InternalMatomoConfiguration}
*
*/
const INTERNAL_MATOMO_CONFIGURATION$1 = new InjectionToken('INTERNAL_MATOMO_CONFIGURATION');
function createInternalMatomoConfiguration() {
const { mode, requireConsent, ...restConfig } = requireNonNull(inject(MATOMO_CONFIGURATION, { optional: true }), CONFIG_NOT_FOUND);
return {
mode: mode ? coerceInitializationMode(mode) : undefined,
disabled: false,
enableLinkTracking: true,
trackAppInitialLoad: !inject(MATOMO_ROUTER_ENABLED),
requireConsent: requireConsent ? coerceConsentRequirement(requireConsent) : 'none',
enableJSErrorTracking: false,
runOutsideAngularZone: true,
disableCampaignParameters: false,
acceptDoNotTrack: false,
excludedQueryParams: [],
...restConfig,
};
}
/**
* For internal use only. Injection token for deferred {@link InternalMatomoConfiguration}.
*
*/
const DEFERRED_INTERNAL_MATOMO_CONFIGURATION = new InjectionToken('DEFERRED_INTERNAL_MATOMO_CONFIGURATION');
function createDeferredInternalMatomoConfiguration() {
const base = inject(INTERNAL_MATOMO_CONFIGURATION$1);
let resolveFn;
const configuration = new Promise(resolve => (resolveFn = resolve));
return {
configuration,
markReady(configuration) {
requireNonNull(resolveFn, 'resolveFn')({
...base,
...configuration,
});
},
};
}
/**
* For internal use only. Injection token for fully loaded async {@link InternalMatomoConfiguration}.
*
*/
const ASYNC_INTERNAL_MATOMO_CONFIGURATION = new InjectionToken('ASYNC_INTERNAL_MATOMO_CONFIGURATION');
/** @deprecated Use {@link MatomoInitializationBehavior} instead */
var MatomoInitializationMode;
(function (MatomoInitializationMode) {
/**
* Automatically inject matomo script using provided configuration
*
* @deprecated Use `'auto'` instead
*/
MatomoInitializationMode[MatomoInitializationMode["AUTO"] = 0] = "AUTO";
/**
* Do not inject Matomo script. In this case, initialization script must be provided
*
* @deprecated Use `'manual'` instead
*/
MatomoInitializationMode[MatomoInitializationMode["MANUAL"] = 1] = "MANUAL";
/**
* Automatically inject matomo script when deferred tracker configuration is provided using `MatomoInitializerService.initializeTracker()`.
*
* @deprecated Use `'deferred'` instead
*/
MatomoInitializationMode[MatomoInitializationMode["AUTO_DEFERRED"] = 2] = "AUTO_DEFERRED";
})(MatomoInitializationMode || (MatomoInitializationMode = {}));
function coerceInitializationMode(value) {
switch (value) {
case MatomoInitializationMode.AUTO:
return 'auto';
case MatomoInitializationMode.MANUAL:
return 'manual';
case MatomoInitializationMode.AUTO_DEFERRED:
return 'deferred';
default:
return value;
}
}
/** @deprecated Use {@link MatomoConsentRequirement} instead */
var MatomoConsentMode;
(function (MatomoConsentMode) {
/** Do not require any consent, always track users */
MatomoConsentMode[MatomoConsentMode["NONE"] = 0] = "NONE";
/** Require cookie consent */
MatomoConsentMode[MatomoConsentMode["COOKIE"] = 1] = "COOKIE";
/** Require tracking consent */
MatomoConsentMode[MatomoConsentMode["TRACKING"] = 2] = "TRACKING";
})(MatomoConsentMode || (MatomoConsentMode = {}));
function coerceConsentRequirement(value) {
switch (value) {
case MatomoConsentMode.NONE:
return 'none';
case MatomoConsentMode.COOKIE:
return 'cookie';
case MatomoConsentMode.TRACKING:
return 'tracking';
default:
return value;
}
}
function isAutoConfigurationMode(config) {
return (config.mode == null || config.mode === 'auto' || config.mode === MatomoInitializationMode.AUTO);
}
function hasMainTrackerConfiguration(config) {
// If one is undefined, both should be
return config.siteId != null && config.trackerUrl != null;
}
function isEmbeddedTrackerConfiguration(config) {
return config.scriptUrl != null && !hasMainTrackerConfiguration(config);
}
function isExplicitTrackerConfiguration(config) {
return hasMainTrackerConfiguration(config) || isMultiTrackerConfiguration(config);
}
function isMultiTrackerConfiguration(config) {
return Array.isArray(config.trackers);
}
function getTrackersConfiguration(config) {
return isMultiTrackerConfiguration(config)
? config.trackers
: [
{
trackerUrl: config.trackerUrl,
siteId: config.siteId,
trackerUrlSuffix: config.trackerUrlSuffix,
},
];
}
function initializeMatomoHolder() {
window._paq = window._paq || [];
}
function trimTrailingUndefinedElements(array) {
const trimmed = [...array];
while (trimmed.length > 0 && trimmed[trimmed.length - 1] === undefined) {
trimmed.pop();
}
return trimmed;
}
function createInternalMatomoTracker() {
const disabled = inject(INTERNAL_MATOMO_CONFIGURATION$1).disabled;
const isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
return disabled || !isBrowser ? new NoopMatomoTracker() : new InternalMatomoTracker();
}
class InternalMatomoTracker {
constructor() {
this.ngZone = inject(NgZone);
this.config = inject(INTERNAL_MATOMO_CONFIGURATION$1);
initializeMatomoHolder();
}
/** Asynchronously call provided method name on matomo tracker instance */
get(getter) {
return this.pushFn(matomo => matomo[getter]());
}
pushFn(fn) {
return new Promise(resolve => {
this.push([
function () {
resolve(fn(this));
},
]);
});
}
push(args) {
if (this.config.runOutsideAngularZone) {
this.ngZone.runOutsideAngular(() => {
window._paq.push(trimTrailingUndefinedElements(args));
});
}
else {
window._paq.push(trimTrailingUndefinedElements(args));
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: InternalMatomoTracker, deps: [], target: i0.ɵɵFactoryTarget.Service }); }
static { this.ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.0", ngImport: i0, type: InternalMatomoTracker, autoProvided: false }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: InternalMatomoTracker, decorators: [{
type: Service,
args: [{ autoProvided: false }]
}], ctorParameters: () => [] });
class NoopMatomoTracker {
/** Asynchronously call provided method name on matomo tracker instance */
async get(_) {
return Promise.reject('MatomoTracker is disabled');
}
push(_) {
// No-op
}
async pushFn(_) {
return Promise.reject('MatomoTracker is disabled');
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: NoopMatomoTracker, deps: [], target: i0.ɵɵFactoryTarget.Service }); }
static { this.ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.0", ngImport: i0, type: NoopMatomoTracker, autoProvided: false }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: NoopMatomoTracker, decorators: [{
type: Service,
args: [{ autoProvided: false }]
}] });
function provideTestingTracker() {
return [
MatomoTestingTracker,
{
provide: InternalMatomoTracker,
useExisting: MatomoTestingTracker,
},
];
}
class MatomoTestingTracker {
constructor() {
this.initStatus = inject(ApplicationInitStatus);
/** Get list of all calls until initialization */
this.callsOnInit = [];
/** Get list of all calls after initialization */
this.callsAfterInit = [];
}
/** Get a copy of all calls since application startup */
get calls() {
return [...this.callsOnInit, ...this.callsAfterInit];
}
countCallsAfterInit(command) {
return this.callsAfterInit.filter(call => call[0] === command).length;
}
reset() {
this.callsOnInit = [];
this.callsAfterInit = [];
}
/** Asynchronously call provided method name on matomo tracker instance */
async get(_) {
return Promise.reject('MatomoTracker is disabled');
}
push(arg) {
if (this.initStatus.done) {
this.callsAfterInit.push(arg);
}
else {
this.callsOnInit.push(arg);
}
}
async pushFn(_) {
return Promise.reject('MatomoTracker is disabled');
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: MatomoTestingTracker, deps: [], target: i0.ɵɵFactoryTarget.Service }); }
static { this.ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.0", ngImport: i0, type: MatomoTestingTracker, autoProvided: false }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: MatomoTestingTracker, decorators: [{
type: Service,
args: [{ autoProvided: false }]
}] });
const ALREADY_INJECTED_ERROR = 'Matomo trackers have already been initialized';
const ALREADY_INITIALIZED_ERROR = 'Matomo has already been initialized';
function isECommerceCategoryView(param) {
return (typeof param === 'object' && Object.keys(param).length === 1 && param.productCategory != null);
}
function isECommerceItemView(param) {
return typeof param === 'object' && 'productSKU' in param;
}
class MatomoTracker {
constructor() {
this.delegate = inject((InternalMatomoTracker));
this._pageViewTracked = new Subject();
this.pageViewTracked = this._pageViewTracked.asObservable();
inject(DestroyRef).onDestroy(() => this._pageViewTracked.complete());
}
/**
* Logs a visit to this page.
*
* @param [customTitle] Optional title of the visited page.
*/
trackPageView(customTitle) {
this.delegate.push(['trackPageView', customTitle]);
this._pageViewTracked.next();
}
/**
* 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.
* @param [customData] Optional custom data for the event.
*/
trackEvent(category, action, name, value, customData) {
this.delegate.push(['trackEvent', category, action, name, value, customData]);
}
/**
* 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.
* @param [customData] Optional custom data for the search query.
*/
trackSiteSearch(keyword, category, resultsCount, customData) {
this.delegate.push(['trackSiteSearch', keyword, category, resultsCount, customData]);
}
/**
* 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.
* @param [customData] Optional custom data for the goal.
*/
trackGoal(idGoal, customRevenue, customData) {
this.delegate.push(['trackGoal', idGoal, customRevenue, customData]);
}
/**
* 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.
* @param [customData] Optional custom data for the link.
*/
trackLink(url, linkType, customData) {
this.delegate.push(['trackLink', url, linkType, customData]);
}
/**
* Scans the entire DOM for all content blocks and tracks all impressions once the DOM ready event has been triggered.
*
*/
trackAllContentImpressions() {
this.delegate.push(['trackAllContentImpressions']);
}
/**
* 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.
*/
trackVisibleContentImpressions(checkOnScroll, timeInterval) {
this.delegate.push(['trackVisibleContentImpressions', checkOnScroll, timeInterval]);
}
/**
* 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.
*/
trackContentImpressionsWithinNode(node) {
this.delegate.push(['trackContentImpressionsWithinNode', node]);
}
/**
* 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.
*/
trackContentInteractionNode(node, contentInteraction) {
this.delegate.push(['trackContentInteractionNode', node, contentInteraction]);
}
/**
* Tracks a content impression using the specified values.
*
* @param contentName Content name.
* @param contentPiece Content piece.
* @param contentTarget Content target.
*/
trackContentImpression(contentName, contentPiece, contentTarget) {
this.delegate.push(['trackContentImpression', contentName, contentPiece, contentTarget]);
}
/**
* Tracks a content interaction using the specified values.
*
* @param contentInteraction Content interaction.
* @param contentName Content name.
* @param contentPiece Content piece.
* @param contentTarget Content target.
*/
trackContentInteraction(contentInteraction, contentName, contentPiece, contentTarget) {
this.delegate.push([
'trackContentInteraction',
contentInteraction,
contentName,
contentPiece,
contentTarget,
]);
}
/**
* Logs all found content blocks within a page to the console. This is useful to debug / test content tracking.
*/
logAllContentBlocksOnPage() {
this.delegate.push(['logAllContentBlocksOnPage']);
}
/**
* Send a ping request
* <p>
* Ping requests do not track new actions.
* If they are sent within the standard visit length, they will update the existing visit time.
* If sent after the standard visit length, ping requests will be ignored.
* See also {@link #enableHeartBeatTimer enableHeartBeatTimer()}.
*
* @see enableHeartBeatTimer
*/
ping() {
this.delegate.push(['ping']);
}
/**
* Install 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) {
this.delegate.push(['enableHeartBeatTimer', delay]);
}
/**
* Disable heartbeat if it was previously activated
*/
disableHeartBeatTimer() {
this.delegate.push(['disableHeartBeatTimer']);
}
/**
* Installs link tracking on all applicable link elements.
*
* @param usePseudoClickHandler 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(usePseudoClickHandler = false) {
this.delegate.push(['enableLinkTracking', usePseudoClickHandler]);
}
/** Disables page performance tracking */
disablePerformanceTracking() {
this.delegate.push(['disablePerformanceTracking']);
}
/**
* 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.
*
*/
enableCrossDomainLinking() {
this.delegate.push(['enableCrossDomainLinking']);
}
/**
* 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.
*/
setCrossDomainLinkingTimeout(timeout) {
this.delegate.push(['setCrossDomainLinkingTimeout', timeout]);
}
/**
* Get the query parameter to append to links to handle cross domain linking.
*
* Use this to add cross domain support for links that are added to the DOM dynamically
*/
getCrossDomainLinkingUrlParameter() {
return this.delegate.get('getCrossDomainLinkingUrlParameter');
}
/**
* Set array of referrers where campaign parameters should be ignored
*/
setIgnoreCampaignsForReferrers(referrers) {
this.delegate.push(['setIgnoreCampaignsForReferrers', referrers]);
}
/**
* Get array of referrers where campaign parameters should be ignored
*/
getIgnoreCampaignsForReferrers() {
return this.delegate.get('getIgnoreCampaignsForReferrers');
}
/**
* Overrides document.title
*
* @param title Title of the document.
*/
setDocumentTitle(title) {
this.delegate.push(['setDocumentTitle', title]);
}
/**
* Set 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.
*/
setDomains(domains) {
this.delegate.push(['setDomains', domains]);
}
/**
* Override the page's reported URL.
*
* @param url URL to be reported for the page.
*/
setCustomUrl(url) {
this.delegate.push(['setCustomUrl', url]);
}
/**
* Overrides the detected Http-Referer.
*
* @param url URL to be reported for the referer.
*/
setReferrerUrl(url) {
this.delegate.push(['setReferrerUrl', url]);
}
/**
* Specifies the website ID.<br />
* Redundant: can be specified in getTracker() constructor.
*
* @param siteId Site ID for the tracker.
*/
setSiteId(siteId) {
this.delegate.push(['setSiteId', siteId]);
}
/**
* Specify the Matomo HTTP API URL endpoint. Points to the root directory of matomo,
* e.g. https://matomo.example.org/ or https://example.org/matomo/.
*
* This function is only useful when the 'Overlay' report is not working. By default, you do not need to use this function.
*
* @deprecated use `setAPIUrl` instead
*/
setApiUrl(url) {
this.setAPIUrl(url);
}
/**
* Set the URL of the Matomo API. It is used for Page Overlay.
*
* This method should only be called when the API URL differs from the tracker URL.
* By default, you do not need to use this function.
*
* @param url URL for the Matomo API.
*/
setAPIUrl(url) {
this.delegate.push(['setAPIUrl', url]);
}
/**
* Specifies the Matomo server URL.<br />
* Redundant: can be specified in getTracker() constructor.
*
* @param url URL for the Matomo server.
*/
setTrackerUrl(url) {
this.delegate.push(['setTrackerUrl', url]);
}
/**
* Register an additional Matomo server<br />
* Redundant: can be specified in getTracker() constructor.
*
* @param url URL for the Matomo server.
* @param siteId Site ID for the tracker
*/
addTracker(url, siteId) {
this.delegate.push(['addTracker', url, siteId]);
}
/**
* Returns the Matomo server URL.
*
* @returns Promise for the Matomo server URL.
*/
getMatomoUrl() {
return this.delegate.get('getMatomoUrl');
}
/** @deprecated use `getMatomoUrl` instead */
getPiwikUrl() {
return this.delegate.get('getPiwikUrl');
}
/**
* 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 this.delegate.get('getCurrentUrl');
}
/**
* Set 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) {
this.delegate.push(['setDownloadClasses', classes]);
}
/**
* Set list of 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) {
this.delegate.push(['setDownloadExtensions', extensions]);
}
/**
* Set 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) {
this.delegate.push(['addDownloadExtensions', extensions]);
}
/**
* Set 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) {
this.delegate.push(['removeDownloadExtensions', extensions]);
}
/**
* Set 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) {
this.delegate.push(['setIgnoreClasses', classes]);
}
/**
* Set 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) {
this.delegate.push(['setLinkClasses', classes]);
}
/**
* Set delay for link tracking (in milliseconds).
*
* @param delay Delay, in milliseconds, for link tracking.
*/
setLinkTrackingTimer(delay) {
this.delegate.push(['setLinkTrackingTimer', delay]);
}
/**
* Returns delay for link tracking.
*
* @returns Promise for the delay in milliseconds.
*/
getLinkTrackingTimer() {
return this.delegate.get('getLinkTrackingTimer');
}
/**
* Set to true to not 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) {
this.delegate.push(['discardHashTag', value]);
}
/**
* 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.
*
* <b>This feature has been deprecated since Matomo 4. Any call will be ignored with Matomo 4. Use {@link setPagePerformanceTiming setPagePerformanceTiming()} instead.</b>
*
* @param generationTime Time, in milliseconds, of the page generation.
*/
setGenerationTimeMs(generationTime) {
this.delegate.push(['setGenerationTimeMs', generationTime]);
}
setPagePerformanceTiming(networkTimeInMsOrTimings, serverTimeInMs, transferTimeInMs, domProcessingTimeInMs, domCompletionTimeInMs, onloadTimeInMs) {
let networkTimeInMs;
if (typeof networkTimeInMsOrTimings === 'object' && !!networkTimeInMsOrTimings) {
networkTimeInMs = networkTimeInMsOrTimings.networkTimeInMs;
serverTimeInMs = networkTimeInMsOrTimings.serverTimeInMs;
transferTimeInMs = networkTimeInMsOrTimings.transferTimeInMs;
domProcessingTimeInMs = networkTimeInMsOrTimings.domProcessingTimeInMs;
domCompletionTimeInMs = networkTimeInMsOrTimings.domCompletionTimeInMs;
onloadTimeInMs = networkTimeInMsOrTimings.onloadTimeInMs;
}
else {
networkTimeInMs = networkTimeInMsOrTimings;
}
this.delegate.push([
'setPagePerformanceTiming',
networkTimeInMs,
serverTimeInMs,
transferTimeInMs,
domProcessingTimeInMs,
domCompletionTimeInMs,
onloadTimeInMs,
]);
}
getCustomPagePerformanceTiming() {
return this.delegate.get('getCustomPagePerformanceTiming');
}
/**
* Appends a custom string to the end of the HTTP request to matomo.php.
*
* @param appendToUrl String to append to the end of the HTTP request to matomo.php.
*/
appendToTrackingUrl(appendToUrl) {
this.delegate.push(['appendToTrackingUrl', appendToUrl]);
}
/** Set to `true` to not track users who opt out of tracking using <i>Do Not Track</i> setting */
setDoNotTrack(doNotTrack) {
this.delegate.push(['setDoNotTrack', doNotTrack]);
}
/**
* Enables a frame-buster to prevent the tracked web page from being framed/iframed.
*/
killFrame() {
this.delegate.push(['killFrame']);
}
/**
* 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) {
this.delegate.push(['redirectFile', url]);
}
/**
* 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.
*/
setHeartBeatTimer(minimumVisitLength, heartBeatDelay) {
this.delegate.push(['setHeartBeatTimer', minimumVisitLength, heartBeatDelay]);
}
/**
* Returns the 16 characters ID for the visitor.
*
* @returns Promise for the the 16 characters ID for the visitor.
*/
getVisitorId() {
return this.delegate.get('getVisitorId');
}
/**
* Set the 16 characters ID for the visitor
* <p/>
* The visitorId needs to be a 16 digit hex string.
* It won't be persisted in a cookie and needs to be set on every new page load.
*
* @param visitorId a 16 digit hex string
*/
setVisitorId(visitorId) {
this.delegate.push(['setVisitorId', visitorId]);
}
/**
* Returns the visitor cookie contents in an array.
*
* @returns Promise for the cookie contents in an array.
*
* TODO better return type
*/
getVisitorInfo() {
return this.delegate.get('getVisitorInfo');
}
/**
* 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 this.delegate.get('getAttributionInfo');
}
/**
* Returns the attribution campaign name.
*
* @returns Promise for the the attribution campaign name.
*/
getAttributionCampaignName() {
return this.delegate.get('getAttributionCampaignName');
}
/**
* Returns the attribution campaign keyword.
*
* @returns Promise for the attribution campaign keyword.
*/
getAttributionCampaignKeyword() {
return this.delegate.get('getAttributionCampaignKeyword');
}
/**
* Returns the attribution referrer timestamp.
*
* @returns Promise for the attribution referrer timestamp (as string).
*/
getAttributionReferrerTimestamp() {
return this.delegate.get('getAttributionReferrerTimestamp');
}
/**
* Returns the attribution referrer URL.
*
* @returns Promise for the attribution referrer URL
*/
getAttributionReferrerUrl() {
return this.delegate.get('getAttributionReferrerUrl');
}
/**
* Returns the User ID string if it was set.
*
* @returns Promise for the User ID for the visitor.
*/
getUserId() {
return this.delegate.get('getUserId');
}
/**
* Set a User ID to this user (such as an email address or a username).
*
* @param userId User ID to set for the current visitor.
*/
setUserId(userId) {
this.delegate.push(['setUserId', userId]);
}
/**
* Reset the User ID which also generates a new Visitor ID.
*
*/
resetUserId() {
this.delegate.push(['resetUserId']);
}
/**
* Override PageView id for every use of logPageView() <b>THIS SHOULD PROBABLY NOT BE CALLED IN A SINGLE-PAGE APP!</b>
*
* Do not use this if you call trackPageView() multiple times during tracking (e.g. when tracking a single page application)
*
* @param pageView
*/
setPageViewId(pageView) {
this.delegate.push(['setPageViewId', pageView]);
}
/**
* Returns the PageView id. If not set manually using setPageViewId, this method will return the dynamic PageView id, used in the last tracked page view, or undefined if no page view was tracked yet
*/
getPageViewId() {
return this.delegate.get('getPageViewId');
}
setCustomData(...args) {
this.delegate.push(['setCustomData', ...args]);
}
/**
* Retrieves custom data.
*
* @returns Promise for the value of custom data.
*/
getCustomData() {
return this.delegate.get('getCustomData');
}
/**
* Set 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.
*/
setCustomVariable(index, name, value, scope) {
this.delegate.push(['setCustomVariable', index, name, value, scope]);
}
/**
* Deletes a custom variable.
*
* @param index Index of the custom variable to delete.
* @param scope Scope of the custom variable to delete.
*/
deleteCustomVariable(index, scope) {
this.delegate.push(['deleteCustomVariable', index, scope]);
}
/**
* Deletes all custom variables.
*
* @param scope Scope of the custom variables to delete.
*/
deleteCustomVariables(scope) {
this.delegate.push(['deleteCustomVariables', scope]);
}
/**
* 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.
*/
getCustomVariable(index, scope) {
return this.delegate.pushFn(matomo => matomo.getCustomVariable(index, scope));
}
/**
* 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.)
*
*/
storeCustomVariablesInCookie() {
this.delegate.push(['storeCustomVariablesInCookie']);
}
/**
* Set 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.
*/
setCustomDimension(customDimensionId, customDimensionValue) {
this.delegate.push(['setCustomDimension', customDimensionId, customDimensionValue]);
}
/**
* Deletes a custom dimension.<br />
* (requires Matomo 2.15.1 + Custom Dimensions plugin)
*
* @param customDimensionId ID of the custom dimension to delete.
*/
deleteCustomDimension(customDimensionId) {
this.delegate.push(['deleteCustomDimension', customDimensionId]);
}
/**
* Retrieve a custom dimension.<br />
* (requires Matomo 2.15.1 + Custom Dimensions plugin)
*
* @param customDimensionId ID of the custom dimension to retrieve.
* @return Promise for the value for the requested custom dimension.
*/
getCustomDimension(customDimensionId) {
return this.delegate.pushFn(matomo => matomo.getCustomDimension(customDimensionId));
}
/**
* Set campaign name parameter(s).
*
* @param name Name of the campaign
*/
setCampaignNameKey(name) {
this.delegate.push(['setCampaignNameKey', name]);
}
/**
* Set campaign keyword parameter(s).
*
* @param keyword Keyword parameter(s) of the campaign.
*/
setCampaignKeywordKey(keyword) {
this.delegate.push(['setCampaignKeywordKey', keyword]);
}
/**
* Set to true 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.
*/
setConversionAttributionFirstReferrer(conversionToFirstReferrer) {
this.delegate.push(['setConversionAttributionFirstReferrer', conversionToFirstReferrer]);
}
setEcommerceView(productOrSKU, productName, productCategory, price) {
if (isECommerceCategoryView(productOrSKU)) {
this.delegate.push(['setEcommerceView', false, false, productOrSKU.productCategory]);
}
else if (isECommerceItemView(productOrSKU)) {
this.delegate.push([
'setEcommerceView',
productOrSKU.productSKU,
productOrSKU.productName,
productOrSKU.productCategory,
productOrSKU.price,
]);
}
else {
this.delegate.push(['setEcommerceView', productOrSKU, productName, productCategory, price]);
}
}
addEcommerceItem(productOrSKU, productName, productCategory, price, quantity) {
if (typeof productOrSKU === 'string') {
this.delegate.push([
'addEcommerceItem',
productOrSKU,
productName,
productCategory,
price,
quantity,
]);
}
else {
this.delegate.push([
'addEcommerceItem',
productOrSKU.productSKU,
productOrSKU.productName,
productOrSKU.productCategory,
productOrSKU.price,
productOrSKU.quantity,
]);
}
}
/**
* Remove the specified product from the untracked ecommerce order
*
* @param productSKU SKU of the product to remove.
*/
removeEcommerceItem(productSKU) {
this.delegate.push(['removeEcommerceItem', productSKU]);
}
/**
* Remove all products in the untracked ecommerce order
*
* Note: This is done automatically after {@link #trackEcommerceOrder trackEcommerceOrder()} is called
*/
clearEcommerceCart() {
this.delegate.push(['clearEcommerceCart']);
}
/**
* Return all ecommerce items currently in the untracked ecommerce order
* <p/>
* The returned array will be a copy, so changing it won't affect the ecommerce order.
* To affect what gets tracked, use the {@link #addEcommerceItem addEcommerceItem()}, {@link #removeEcommerceItem removeEcommerceItem()},
* {@link #clearEcommerceCart clearEcommerceCart()} methods.
* Use this method to see what will be tracked before you track an order or cart update.
*/
getEcommerceItems() {
return this.delegate.get('getEcommerceItems');
}
/**
* 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) {
this.delegate.push(['trackEcommerceCartUpdate', grandTotal]);
}
/**
* 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) {
this.delegate.push([
'trackEcommerceOrder',
orderId,
grandTotal,
subTotal,
tax,
shipping,
discount,
]);
}
/**
* Require nothing is tracked until a user consents
*
* By default the Matomo tracker assumes consent to tracking.
*
* @see `requireConsent` module configuration property
*/
requireConsent() {
this.delegate.push(['requireConsent']);
}
/**
* Mark that the current user has consented
*
* The consent is one-time only, so in a subsequent browser session, the user will have to consent again.
* To remember consent, see {@link rememberConsentGiven}.
*/
setConsentGiven() {
this.delegate.push(['setConsentGiven']);
}
/**
* Mark that the current user has consented, and remembers this consent through a browser cookie.
*
* The next time the user visits the site, Matomo will remember that they consented, and track them.
* If you call this method, you do not need to call {@link setConsentGiven}.
*
* @param hoursToExpire After how many hours the consent should expire. By default the consent is valid
* for 30 years unless cookies are deleted by the user or the browser prior to this
*/
rememberConsentGiven(hoursToExpire) {
this.delegate.push(['rememberConsentGiven', hoursToExpire]);
}
/**
* Remove a user's consent, both if the consent was one-time only and if the consent was remembered.
*
* After calling this method, the user will have to consent again in order to be tracked.
*/
forgetConsentGiven() {
this.delegate.push(['forgetConsentGiven']);
}
/** Return whether the current visitor has given consent previously or not */
hasRememberedConsent() {
return this.delegate.get('hasRememberedConsent');
}
/** Return whether the current visitor has given consent or not */
hasConsent() {
return this.delegate.get('hasConsent');
}
/**
* If consent was given, returns the timestamp when the visitor gave consent
*
* Only works if {@link rememberConsentGiven} was used and not when {@link setConsentGiven} was used.
* The timestamp is the local timestamp which depends on the visitors time.
*/
getRememberedConsent() {
return this.delegate.get('getRememberedConsent');
}
/** Return whether {@link requireConsent} was called previously */
isConsentRequired() {
return this.delegate.get('isConsentRequired');
}
/**
* Require no cookies are used
*
* By default the Matomo tracker assumes consent to using cookies
*/
requireCookieConsent() {
this.delegate.push(['requireCookieConsent']);
}
/**
* Mark that the current user has consented to using cookies
*
* The consent is one-time only, so in a subsequent browser session, the user will have to consent again.
* To remember cookie consent, see {@link rememberCookieConsentGiven}.
*/
setCookieConsentGiven() {
this.delegate.push(['setCookieConsentGiven']);
}
/**
* Mark that the current user has consented to using cookies, and remembers this consent through a browser cookie.
*
* The next time the user visits the site, Matomo will remember that they consented, and use cookies.
* If you call this method, you do not need to call {@link setCookieConsentGiven}.
*
* @param hoursToExpire After how many hours the cookie consent should expire. By default the consent is valid
* for 30 years unless cookies are deleted by the user or the browser prior to this
*/
rememberCookieConsentGiven(hoursToExpire) {
this.delegate.push(['rememberCookieConsentGiven', hoursToExpire]);
}
/**
* Remove a user's cookie consent, both if the consent was one-time only and if the consent was remembered.
*
* After calling this method, the user will have to consent again in order for cookies to be used.
*/
forgetCookieConsentGiven() {
this.delegate.push(['forgetCookieConsentGiven']);
}
getRememberedCookieConsent() {
return this.delegate.get('getRememberedCookieConsent');
}
/** Return whether cookies are currently enabled or disabled */
areCookiesEnabled() {
return this.delegate.get('areCookiesEnabled');
}
/** After calling this function, the user will be opted out and no longer be tracked */
optUserOut() {
this.delegate.push(['optUserOut']);
}
/** After calling this method the user will be tracked again */
forgetUserOptOut() {
this.delegate.push(['forgetUserOptOut']);
}
/**
* Return whether the user is opted out or not
*
* Note: This method might not return the correct value if you are using the opt out iframe.
*/
isUserOptedOut() {
return this.delegate.get('isUserOptedOut');
}
/**
* Disables all first party cookies.<br />
* Existing Matomo cookies for this websites will be deleted on the next page view.
*/
disableCookies() {
this.delegate.push(['disableCookies']);
}
/**
* Deletes the tracking cookies currently set (useful when creating new visits).
*/
deleteCookies() {
this.delegate.push(['deleteCookies']);
}
/**
* Returns whether cookies are enabled and supported by this browser.
*
* @returns Promise for the support and activation of cookies.
*/
hasCookies() {
return this.delegate.get('hasCookies');
}
/**
* Set the tracking cookie name prefix.<br />
* Default prefix is 'pk'.
*
* @param prefix Prefix for the tracking cookie names.
*/
setCookieNamePrefix(prefix) {
this.delegate.push(['setCookieNamePrefix', prefix]);
}
/**
* Set 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) {
this.delegate.push(['setCookieDomain', domain]);
}
/**
* Set the path of the tracking cookies.<br />
* Default is '/'.
*
* @param