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

Add getEcommerceItems getter #567

Closed
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Prefix the change with one of these keywords:
- _Security_: in case of vulnerabilities.

## [0.5.0]
- Added: `getEcommerceItems` getter
- Added: Support outbound links on `<a>` child elements.
- Added: `removeEcommerceItem` and `clearEcommerceCart` action

Expand Down
1 change: 1 addition & 0 deletions packages/js/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const tracker = new MatomoTracker({
seconds: 10 // optional, default value: `15
},
linkTracking: false, // optional, default value: true
alwaysUseSendBeacon: true, // optional, default value: true
configurations: { // optional, default value: {}
// any valid matomo configuration, all below are optional
disableCookies: true,
Expand Down
38 changes: 38 additions & 0 deletions packages/js/src/MatomoTracker.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { TRACK_TYPES } from './constants'
import {
AsyncTracker,
EcommerceItems,
AddEcommerceItemParams,
RemoveEcommerceItemParams,
CustomDimension,
Expand All @@ -16,6 +18,8 @@ import {
class MatomoTracker {
mutationObserver?: MutationObserver

private asyncTrackers?: AsyncTracker[]

constructor(userOptions: UserOptions) {
if (!userOptions.urlBase) {
throw new Error('Matomo urlBase is required.')
Expand All @@ -36,6 +40,7 @@ class MatomoTracker {
disabled,
heartBeat,
linkTracking = true,
alwaysUseSendBeacon = true,
configurations = {},
}: UserOptions) {
const normalizedUrlBase =
Expand Down Expand Up @@ -87,6 +92,15 @@ class MatomoTracker {
scriptElement.async = true
scriptElement.defer = true
scriptElement.src = srcUrl || `${normalizedUrlBase}matomo.js`
scriptElement.onload = () => {
this.asyncTrackers = window.Matomo.getAsyncTrackers()

// If enabled (default), always use sendBeacon if the browser supports it
// Disabling this makes sense when you're waiting for a tracking operation to be done and immediately do a page redirect afterwards.
if (alwaysUseSendBeacon === false) {
this.callMethod('disableAlwaysUseSendBeacon')
}
}

if (scripts && scripts.parentNode) {
scripts.parentNode.insertBefore(scriptElement, scripts)
Expand Down Expand Up @@ -235,6 +249,11 @@ class MatomoTracker {
)
}

// Return all ecommerce items currently in the untracked ecommerce order.
// https://matomo.org/docs/ecommerce-analytics
getEcommerceItems(): EcommerceItems {
return (this.callMethod('getEcommerceItems') || {}) as EcommerceItems
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we use a generic here instead of casting it? Then it would be this.callMethod<EcommerceItems>

}
// Removes a product from an Ecommerce order to be tracked via trackEcommerceOrder.
// https://matomo.org/docs/ecommerce-analytics
removeEcommerceItem({ sku }: RemoveEcommerceItemParams): void {
Expand Down Expand Up @@ -328,6 +347,25 @@ class MatomoTracker {
}
}

/**
* Calls a specific matomo method which is helpful for any non-push action (getter).
* For example `getEcommerceItems`
*
* @param name The name of the method to be called.
* @param args The arguments which gets passed to the called method.
*/
private callMethod(name: string, ...args: unknown[]): unknown {
if (this.asyncTrackers && this.asyncTrackers.length) {
const asyncTracker = this.asyncTrackers[0] as Record<
string,
(args?: unknown) => unknown
>

return asyncTracker[name](...args)
}
return undefined
}

/**
* Pushes an instruction to Matomo for execution, this is equivalent to pushing entries into the `_paq` array.
*
Expand Down
3 changes: 3 additions & 0 deletions packages/js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import * as types from './types'
declare global {
interface Window {
_paq: [string, ...any[]][]
Matomo: {
getAsyncTrackers: () => types.AsyncTracker[]
}
}
}

Expand Down
8 changes: 8 additions & 0 deletions packages/js/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export type AsyncTracker = any

export interface CustomDimension {
id: number
value: string
Expand All @@ -15,6 +17,7 @@ export interface UserOptions {
seconds?: number
}
linkTracking?: boolean
alwaysUseSendBeacon?: boolean
configurations?: {
[key: string]: any
}
Expand Down Expand Up @@ -75,3 +78,8 @@ export interface SetEcommerceViewParams {
productCategory?: string
productPrice?: number
}

export type EcommerceItems = Record<
number,
[string, string, string, number, number]
>