Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Change interface to prototype chain #178

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 17 additions & 31 deletions packages/js/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ const MatomoInstance = new window.MatomoTracker({ ... })
```html
<script src="./bundle.min.js"></script>
<script>
const MatomoInstance = new window.MatomoTracker.default({
/* setup */
})
const MatomoInstance = new window.MatomoTracker.default('https://LINK.TO.DOMAIN').initialize()

// Load the event listeners
MatomoInstance.trackEvents()
Expand All @@ -38,34 +36,26 @@ Before you're able to use this Matomo Tracker you need to initialize Matomo with
**Initialize:**

```js
const MatomoInstance = new window.MatomoTracker({
urlBase: 'https://LINK.TO.DOMAIN',
siteId: 3, // optional, default value: `1`
userId: 'UID76903202', // optional, default value: `undefined`.
trackerUrl: 'https://LINK.TO.DOMAIN/tracking.php', // optional, default value: `${urlBase}matomo.php`
srcUrl: 'https://LINK.TO.DOMAIN/tracking.js', // optional, default value: `${urlBase}matomo.js`
heartBeat: { // optional, enabled by default
active: true, // optional, default value: true
seconds: 10 // optional, default value: `15
}
linkTracking: false, // optional, default value: true
configurations: { // optional, default value: {}
// any valid matomo configuration, all below are optional
disableCookies: true,
setSecureCookie: true,
setRequestMethod: 'POST'
}
})
const MatomoInstance = new window.MatomoTracker('https://LINK.TO.DOMAIN')
.setTrackerUrl('https://LINK.TO.DOMAIN/tracking.php') // optional, default value: `${urlBase}matomo.php`
.scriptPath('tracking.js') // optional, default value: `matomo.js`
.setSiteId(3) // optional, default value: `1`
.setUserId('UID76903202') // optional, default value: `undefined`.
.enableHeartBeatTimer(10) // optional, default value: `15
.enableLinkTracking(false) // optional, default value: true
.disableCookies()
.disableQueueRequest()
.setRequestMethod('POST')
.setSecureCookie(true)
.requireConsent()
```

After initialization you can use the Matomo Tracker to track events and page views like this:

```js
import MatomoTracker from '@datapunt/matomo-tracker-js'

const MatomoInstance = new MatomoTracker({
/* setup */
})
const MatomoInstance = new MatomoTracker('https://LINK.TO.DOMAIN')

MatomoInstance.trackPageView()

Expand All @@ -88,9 +78,7 @@ By default the Matomo Tracker will send the window's document title and location
```js
import MatomoTracker from '@datapunt/matomo-tracker-js'

const MatomoInstance = new MatomoTracker({
/* setup */
})
const MatomoInstance = new MatomoTracker('https://LINK.TO.DOMAIN')

MatomoInstance.trackPageView({
documentTitle: 'Page title', // optional
Expand Down Expand Up @@ -129,9 +117,7 @@ Next to the tracking of events, this project also supports tracking site searche
```js
import MatomoTracker from '@datapunt/matomo-tracker-js'

const MatomoInstance = new MatomoTracker({
/* setup */
})
const MatomoInstance = new MatomoTracker('https://LINK.TO.DOMAIN')

MatomoInstance.trackSiteSearch({
keyword: 'test',
Expand Down Expand Up @@ -169,7 +155,7 @@ Or if you want to stay away from inline JavaScript events, this project can be u

<script src="./some-dir/bundle.min.js"></script>
<script>
const MatomoInstance = new window.MatomoTracker({ /* setup */ });
const MatomoInstance = new window.MatomoTracker('https://LINK.TO.DOMAIN');

// Load the event listeners
MatomoInstance.trackEvents();
Expand Down
2 changes: 1 addition & 1 deletion packages/js/bundle.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions packages/js/example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@

<script src="../bundle.min.js"></script>
<script>
const MatomoInstance = new window.MatomoTracker.default({
urlBase: 'https://analytics.data.amsterdam.nl',
siteId: 3,
})
const MatomoInstance = new window.MatomoTracker
.default('https://localhost')
.setSiteId(3)

MatomoInstance.initialize()

MatomoInstance.trackEvents()

Expand Down
133 changes: 78 additions & 55 deletions packages/js/src/MatomoTracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,85 +9,70 @@ import {
TrackEcommerceOrderParams,
AddEcommerceItemParams,
SetEcommerceViewParams,
UserOptions,
} from './types'

class MatomoTracker {
urlBase: string
srcPath: string = 'matomo.js'
mutationObserver?: MutationObserver

constructor(userOptions: UserOptions) {
const options = { ...defaultOptions, ...userOptions }
if (!options.urlBase) {
constructor(urlBase: string) {
if (!urlBase) {
throw new Error('Matomo urlBase is required.')
}

MatomoTracker.initialize(options)
}

// Initializes the Matomo Tracker
static initialize({
urlBase,
siteId,
userId,
trackerUrl,
srcUrl,
heartBeat,
linkTracking = true,
configurations = {},
}: UserOptions) {
if (urlBase[urlBase.length - 1] !== '/') {
urlBase = urlBase + '/'
}

if (typeof window !== 'undefined') {
window._paq = window._paq || []

if (window._paq.length === 0) {
window._paq.push([
'setTrackerUrl',
trackerUrl || `${urlBase}matomo.php`,
])
window._paq.push(['setSiteId', siteId])
this.urlBase = urlBase

if (userId) {
window._paq.push(['setUserId', userId])
}
window._paq = window._paq || []
}

Object.entries(configurations).forEach((entry) => {
window._paq.push([entry[0], entry[1]])
})
initialize() {
if (!this.isRuleSet('setTrackerUrl')) {
window._paq.push(['setTrackerUrl', `${this.urlBase}matomo.php`])
}

// accurately measure the time spent on the last pageview of a visit
if (!heartBeat || (heartBeat && heartBeat.active)) {
this.enableHeartBeatTimer(15 || (heartBeat && heartBeat.seconds))
}
if (!this.isRuleSet('setSiteId')) {
window._paq.push(['setSiteId', defaultOptions.siteId])
}

// // measure outbound links and downloads
// // might not work accurately on SPAs because new links (dom elements) are created dynamically without a server-side page reload.
this.enableLinkTracking(linkTracking)
if (!this.isRuleSet('enableHeartBeatTimer')) {
window._paq.push(['enableHeartBeatTimer', defaultOptions.heartBeatTimer])
}

const doc = document
const scriptElement = doc.createElement('script')
const scripts = doc.getElementsByTagName('script')[0]
const doc = document
const scriptElement = doc.createElement('script')
const scripts = doc.getElementsByTagName('script')[0]

scriptElement.type = 'text/javascript'
scriptElement.async = true
scriptElement.defer = true
scriptElement.src = srcUrl || `${urlBase}matomo.js`
scriptElement.type = 'text/javascript'
scriptElement.async = true
scriptElement.defer = true
scriptElement.src = `${this.urlBase}${this.srcPath}`

if (scripts && scripts.parentNode) {
scripts.parentNode.insertBefore(scriptElement, scripts)
}
}
if (scripts && scripts.parentNode) {
scripts.parentNode.insertBefore(scriptElement, scripts)
}
}

static enableHeartBeatTimer(seconds: number) {
window._paq.push(['enableHeartBeatTimer', seconds])
scriptPath(srcPath: string) {
if (!srcPath || srcPath.search(/:\/\//) > -1) {
throw new Error('A valid path is required.')
}

if (srcPath[0] === '/') {
srcPath = srcPath.substring(1)
}

this.srcPath = srcPath

return this
}

static enableLinkTracking(active: boolean) {
window._paq.push(['enableLinkTracking', active])
private isRuleSet(rule: string) {
return window._paq.find((ruleSet: string) => ruleSet[0] === rule)
}

private trackEventsForElements(elements: HTMLElement[]) {
Expand Down Expand Up @@ -311,4 +296,42 @@ class MatomoTracker {
}
}

const methods = {
disableCookies: undefined,
disableQueueRequest: undefined,
// accurately measure the time spent on the last pageview of a visit
enableHeartBeatTimer: Number,
// measure outbound links and downloads
// might not work accurately on SPAs because new links (dom elements) are created dynamically without a server-side page reload.
enableLinkTracking: Boolean,
requireConsent: undefined,
setCookieDomain: String,
setCookieNamePrefix: String,
setCookiePath: String,
setConversionAttributionFirstReferrer: Boolean,
setCustomRequestProcessing: Function,
setReferralCookieTimeout: Number,
setRequestContentType: String,
setRequestMethod: String,
setSecureCookie: Boolean,
setSessionCookieTimeout: Number,
setSiteId: Number,
setTrackerUrl: String,
setUserId: String,
setVisitorCookieTimeout: Number,
}

function createMethod<T>(method: string) {
Object.defineProperty(MatomoTracker.prototype, method, {
value: function (input: T) {
window._paq.push([method, input])
return this
},
})
}

Object.entries(methods).forEach(([method, type]) => {
createMethod<typeof type>(method)
})

export default MatomoTracker
2 changes: 1 addition & 1 deletion packages/js/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const defaultOptions = {
urlBase: null,
heartBeatTimer: 15,
siteId: 1,
}

Expand Down
16 changes: 0 additions & 16 deletions packages/js/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,6 @@ export interface CustomDimension {
value: string
}

export interface UserOptions {
urlBase: string
siteId: number
userId?: string
trackerUrl?: string
srcUrl?: string
heartBeat?: {
active: boolean
seconds?: number
}
linkTracking?: boolean
configurations?: {
[key: string]: any
}
}

export interface TrackPageViewParams {
documentTitle?: string
href?: string | Location
Expand Down
Loading