diff --git a/.eslintrc b/.eslintrc
deleted file mode 100644
index 4c6c567..0000000
--- a/.eslintrc
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "parser": "@typescript-eslint/parser",
- "extends": [
- "standard",
- "standard-react",
- "plugin:prettier/recommended",
- "prettier/standard",
- "prettier/react",
- "plugin:@typescript-eslint/eslint-recommended"
- ],
- "env": {
- "node": true
- },
- "parserOptions": {
- "ecmaVersion": 2020,
- "ecmaFeatures": {
- "legacyDecorators": true,
- "jsx": true
- }
- },
- "settings": {
- "react": {
- "version": "16"
- }
- },
- "rules": {
- "space-before-function-paren": 0,
- "react/prop-types": 0,
- "react/jsx-handler-names": 0,
- "react/jsx-fragments": 0,
- "react/no-unused-prop-types": 0,
- "import/export": 0
- }
-}
diff --git a/.eslintrc.cjs b/.eslintrc.cjs
new file mode 100644
index 0000000..4ecbb98
--- /dev/null
+++ b/.eslintrc.cjs
@@ -0,0 +1,16 @@
+/** @type {import('eslint').Linter.Config} */
+const config = {
+ parser: '@typescript-eslint/parser',
+ extends: [
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/recommended-type-checked',
+ ],
+ plugins: ['@typescript-eslint'],
+ ignorePatterns:[".eslintrc.cjs", "example"],
+ parserOptions: {
+ project:true,
+ tsconfigRootDir: __dirname,
+ },
+}
+
+module.exports = config
diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 0000000..3462e8c
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+v18.19.0
\ No newline at end of file
diff --git a/.prettierrc b/.prettierrc
index a9646d4..e87d615 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -4,7 +4,7 @@
"semi": false,
"tabWidth": 2,
"bracketSpacing": true,
- "jsxBracketSameLine": false,
+ "bracketSameLine": false,
"arrowParens": "always",
"trailingComma": "none"
}
diff --git a/README.md b/README.md
index aaeb3fc..873d7ee 100644
--- a/README.md
+++ b/README.md
@@ -190,7 +190,7 @@ Custom events enable tracking visitor actions that are not predefined in the exi
import { CustomEvent } from '@piwikpro/react-piwik-pro'
```
#### Methods
-* `trackEvent(category: string, action: string, name?: string, value?: number) ` - Tracks a custom event, e.g. when a visitor interacts with the page.
+* `trackEvent(category: string, action: string, name?: string, value?: number, dimensions?: Object) ` - Tracks a custom event, e.g. when a visitor interacts with the page.
### Site search Service
Site search tracking gives you insights into how visitors interact with the search engine on your website - what they search for and how many results they get back.
diff --git a/example/package-lock.json b/example/package-lock.json
index 38622aa..7ebaed5 100644
--- a/example/package-lock.json
+++ b/example/package-lock.json
@@ -50,15 +50,6 @@
"babel-eslint": "^10.1.0",
"cross-env": "^7.0.3",
"eslint": "^8.56.0",
- "eslint-config-prettier": "^9.1.0",
- "eslint-config-standard": "^17.1.0",
- "eslint-config-standard-react": "^13.0.0",
- "eslint-plugin-import": "^2.29.1",
- "eslint-plugin-node": "^11.1.0",
- "eslint-plugin-prettier": "^5.1.2",
- "eslint-plugin-promise": "^6.1.1",
- "eslint-plugin-react": "^7.33.2",
- "eslint-plugin-standard": "^5.0.0",
"gh-pages": "^6.1.1",
"microbundle-crl": "^0.13.11",
"npm-run-all": "^4.1.5",
diff --git a/example/src/main.tsx b/example/src/main.tsx
index f7892fa..6c657d9 100644
--- a/example/src/main.tsx
+++ b/example/src/main.tsx
@@ -36,5 +36,8 @@ const App = () => (
)
const container = document.getElementById('root')
-// @ts-ignore
+if(!container){
+ throw new Error("#root element not found")
+}
+
createRoot(container).render()
diff --git a/example/src/pages/CustomEventPage.tsx b/example/src/pages/CustomEventPage.tsx
index 038289e..7b04bf1 100644
--- a/example/src/pages/CustomEventPage.tsx
+++ b/example/src/pages/CustomEventPage.tsx
@@ -45,9 +45,15 @@ const CustomEventPage: FunctionComponent = () => {
variant='contained'
onClick={() => {
setFinish(true)
- CustomEvent.trackEvent('user_data_form', 'submit')
+ CustomEvent.trackEvent(
+ 'user_data_form',
+ 'submit',
+ 'success',
+ 10,
+ { dimension1: 'value1' }
+ )
enqueueSnackbar(
- "CustomEvent.trackEvent('user_data_form', 'submit')",
+ "CustomEvent.trackEvent('user_data_form', 'submit', 'success', 10, { dimension1: 'value1' })",
{ variant: 'success' }
)
}}
diff --git a/package.json b/package.json
index cf737ea..de80fde 100644
--- a/package.json
+++ b/package.json
@@ -21,7 +21,10 @@
"test:unit": "cross-env CI=1 react-scripts test --env=jsdom",
"test:watch": "react-scripts test --env=jsdom",
"predeploy": "cd example && yarn install && yarn run build",
- "deploy": "gh-pages -d example/build"
+ "deploy": "gh-pages -d example/build",
+ "format":"prettier src/**/*.ts --list-different",
+ "format:fix":"npm run format -- --write",
+ "typecheck": "tsc --noEmit"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
@@ -41,15 +44,6 @@
"babel-eslint": "^10.1.0",
"cross-env": "^7.0.3",
"eslint": "^8.56.0",
- "eslint-config-prettier": "^9.1.0",
- "eslint-config-standard": "^17.1.0",
- "eslint-config-standard-react": "^13.0.0",
- "eslint-plugin-import": "^2.29.1",
- "eslint-plugin-node": "^11.1.0",
- "eslint-plugin-prettier": "^5.1.2",
- "eslint-plugin-promise": "^6.1.1",
- "eslint-plugin-react": "^7.33.2",
- "eslint-plugin-standard": "^5.0.0",
"gh-pages": "^6.1.1",
"microbundle-crl": "^0.13.11",
"npm-run-all": "^4.1.5",
diff --git a/src/core/index.ts b/src/core/index.ts
index a609325..c603bce 100644
--- a/src/core/index.ts
+++ b/src/core/index.ts
@@ -1,5 +1,3 @@
-import { PiwikProWindow } from '../interfaces/piwikpro.window'
-
function init(containerId: string, containerUrl: string, nonce?: string) {
if (!containerId) {
console.error('Empty tracking code for Piwik Pro.')
@@ -37,7 +35,7 @@ tags.async=!0,tags.src="${containerUrl}/"+id+".js"+qPString,scripts.parentNode.i
export const IS_DEBUG =
(typeof process !== 'undefined' && process.env.NODE_ENV === 'development') ||
- (typeof window !== 'undefined' && (window as PiwikProWindow).IS_DEBUG) ||
+ (typeof window !== 'undefined' && window.IS_DEBUG) ||
false
export default {
diff --git a/src/index.tsx b/src/index.tsx
index 45ab261..f0f858e 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,3 +1,4 @@
+// NOTE: .tsx file extension is required for microbundle-crl to pick up and build the lib
import * as PiwikPro from './core'
export * as PageViews from './services/pageViews/pageViews.service';
diff --git a/src/interfaces/payment.ts b/src/interfaces/payment.ts
index c5a2801..8c0d4d0 100644
--- a/src/interfaces/payment.ts
+++ b/src/interfaces/payment.ts
@@ -1,8 +1,8 @@
export type PaymentInformation = {
- orderId: string;
- grandTotal: number | string;
- subTotal?: number | string;
- tax?: number | string;
- shipping?: number | string;
- discount?: number | string;
-};
+ orderId: string
+ grandTotal: number | string
+ subTotal?: number | string
+ tax?: number | string
+ shipping?: number | string
+ discount?: number | string
+}
diff --git a/src/interfaces/piwikpro.window.ts b/src/interfaces/piwikpro.window.ts
index f8a513a..7cc6276 100644
--- a/src/interfaces/piwikpro.window.ts
+++ b/src/interfaces/piwikpro.window.ts
@@ -1,5 +1,7 @@
-export interface PiwikProWindow extends Window {
- _paq?: any;
- dataLayer?: any;
- IS_DEBUG?: boolean;
+import { AnyData, QueueItem } from './utils'
+
+export interface PiwikProWindow {
+ _paq?: QueueItem[]
+ dataLayer?: AnyData[]
+ IS_DEBUG?: boolean
}
diff --git a/src/interfaces/product.ts b/src/interfaces/product.ts
index 3713ba3..1b613cc 100644
--- a/src/interfaces/product.ts
+++ b/src/interfaces/product.ts
@@ -1,14 +1,14 @@
import { LimitedArrayFiveStrings } from './utils'
-type DimensionId = number;
+type DimensionId = number
export type Product = {
- sku: string,
- name?: string,
- category?: LimitedArrayFiveStrings,
- price?: number,
- quantity?: number,
- brand?: string,
- variant?: string,
- customDimensions?: Record,
+ sku: string
+ name?: string
+ category?: LimitedArrayFiveStrings
+ price?: number
+ quantity?: number
+ brand?: string
+ variant?: string
+ customDimensions?: Record
}
diff --git a/src/interfaces/tracker.ts b/src/interfaces/tracker.ts
new file mode 100644
index 0000000..d5c914f
--- /dev/null
+++ b/src/interfaces/tracker.ts
@@ -0,0 +1,11 @@
+import { VisitorInfo } from './visitorInfo'
+
+export type Tracker = {
+ hasCookies: () => boolean
+ getCustomDimensionValue: (id: string | number) => string | undefined
+ getLinkTrackingTimer: () => number
+ getEcommerceItems: () => object
+ getUserId: () => string
+ getVisitorId: () => string
+ getVisitorInfo: () => VisitorInfo
+}
diff --git a/src/interfaces/utils.ts b/src/interfaces/utils.ts
index f2f38e4..751b357 100644
--- a/src/interfaces/utils.ts
+++ b/src/interfaces/utils.ts
@@ -1 +1,13 @@
-export type LimitedArrayFiveStrings = [string, ...T] | [string, string, string, string, string];
+import { TRACK_EVENT } from '../constants/track-event.constant'
+import { Tracker } from './tracker'
+
+export type LimitedArrayFiveStrings =
+ | [string, ...T]
+ | [string, string, string, string, string]
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export type AnyData = any
+
+export type Dimensions = Record<`dimension${number}`, string>
+
+export type QueueItem = [TRACK_EVENT, ...unknown[]] | [(this: Tracker) => void]
diff --git a/src/interfaces/visitorInfo.ts b/src/interfaces/visitorInfo.ts
new file mode 100644
index 0000000..c89c699
--- /dev/null
+++ b/src/interfaces/visitorInfo.ts
@@ -0,0 +1,9 @@
+export type VisitorInfo = [
+ isNew: '0' | '1',
+ visitorId: string,
+ firstVisitTS: number,
+ previousVisitCount: string | number,
+ currentVisitTS: number,
+ lastVisitTS: number | '',
+ lastEcommerceOrderTS: number | ''
+]
diff --git a/src/services/content-tracking/contentTracking.service.ts b/src/services/content-tracking/contentTracking.service.ts
index 5ba96bd..502c1e4 100644
--- a/src/services/content-tracking/contentTracking.service.ts
+++ b/src/services/content-tracking/contentTracking.service.ts
@@ -7,15 +7,15 @@ export function trackAllContentImpressions() {
]);
}
-export function trackVisibleContentImpressions(checkOnScroll?: boolean, watchIterval?: number) {
+export function trackVisibleContentImpressions(checkOnScroll?: boolean, watchInterval?: number) {
PaqService.push([
TRACK_EVENT.VISIBLE_CONTENT_IMPRESSIONS,
checkOnScroll,
- watchIterval,
+ watchInterval,
]);
}
-export function trackContentImpressionsWithinNode(domNode: any) {
+export function trackContentImpressionsWithinNode(domNode: Node) {
PaqService.push([
TRACK_EVENT.CONTENT_IMPRESSIONS_WITH_NODE,
domNode
@@ -35,7 +35,7 @@ export function logAllContentBlocksOnPage(): void {
PaqService.push([ TRACK_EVENT.LOG_ALL_CONTENT_BLOCKS_ON_PAGE ]);
}
-export function trackContentInteractionNode(domNode: any, contentInteraction: string) {
+export function trackContentInteractionNode(domNode: Node, contentInteraction: string) {
PaqService.push([
TRACK_EVENT.CONTENT_INTERACTION_NODE,
domNode,
diff --git a/src/services/cookie-management/cookieManagement.service.ts b/src/services/cookie-management/cookieManagement.service.ts
index 275faed..992b765 100644
--- a/src/services/cookie-management/cookieManagement.service.ts
+++ b/src/services/cookie-management/cookieManagement.service.ts
@@ -1,4 +1,5 @@
import { TRACK_EVENT } from '../../constants/track-event.constant';
+import { Tracker } from '../../interfaces/tracker';
import { PaqService } from '../paqService/paq.service';
export function disableCookies() {
@@ -20,7 +21,7 @@ export function hasCookies(): Promise {
return new Promise((resolve, reject) => {
try {
PaqService.push([
- function (this: any) {
+ function (this: Tracker) {
resolve(this.hasCookies());
},
]);
diff --git a/src/services/custom-dimensions/customDimensions.service.ts b/src/services/custom-dimensions/customDimensions.service.ts
index bdc4fbf..fd7dd8c 100644
--- a/src/services/custom-dimensions/customDimensions.service.ts
+++ b/src/services/custom-dimensions/customDimensions.service.ts
@@ -1,4 +1,5 @@
import { TRACK_EVENT } from '../../constants/track-event.constant';
+import { Tracker } from '../../interfaces/tracker';
import { PaqService } from '../paqService/paq.service';
export function setCustomDimensionValue(customDimensionId: string | number, customDimensionValue: string) {
@@ -9,11 +10,11 @@ export function deleteCustomDimension(customDimensionId: string) {
PaqService.push([TRACK_EVENT.DELETE_CUSTOM_DIMENSION, customDimensionId]);
}
-export function getCustomDimensionValue(customDimensionId: string | number): Promise {
+export function getCustomDimensionValue(customDimensionId: string | number): Promise {
return new Promise((resolve, reject) => {
try {
PaqService.push([
- function (this: any): void {
+ function (this: Tracker): void {
resolve(this.getCustomDimensionValue(customDimensionId));
},
]);
diff --git a/src/services/custom-events/customEvents.service.ts b/src/services/custom-events/customEvents.service.ts
index 72d9057..1b69942 100644
--- a/src/services/custom-events/customEvents.service.ts
+++ b/src/services/custom-events/customEvents.service.ts
@@ -1,12 +1,14 @@
import { TRACK_EVENT } from '../../constants/track-event.constant';
+import { Dimensions } from '../../interfaces/utils';
import { PaqService } from '../paqService/paq.service';
-export function trackEvent(category: string, action: string, name?: string, value?: number) {
- const eventArguments: any[] = [
+export function trackEvent(category: string, action: string, name?: string, value?: number, dimensions?:Dimensions) {
+ const eventArguments = [
category,
action,
...(name ? [name] : []),
...(name ? [value] : []),
+ ...(dimensions ? [dimensions] : []),
];
PaqService.push([TRACK_EVENT.CUSTOM_EVENT, ...eventArguments])
}
diff --git a/src/services/dataLayer/dataLayer.service.ts b/src/services/dataLayer/dataLayer.service.ts
index a124d99..c75c284 100644
--- a/src/services/dataLayer/dataLayer.service.ts
+++ b/src/services/dataLayer/dataLayer.service.ts
@@ -1,11 +1,14 @@
-import { PiwikProWindow } from '../../interfaces/piwikpro.window';
import { IS_DEBUG } from '../../core';
+import { AnyData } from '../../interfaces/utils';
-export function push(data: any) {
- if (!(window as PiwikProWindow).dataLayer) {
- (window as PiwikProWindow).dataLayer = [];
+
+export function push(
+ data: AnyData
+) {
+ if (!window.dataLayer) {
+ window.dataLayer = [];
}
IS_DEBUG && console.log('DataLayer push', data);
- return (window as PiwikProWindow).dataLayer.push(data);
+ return window.dataLayer.push(data);
}
diff --git a/src/services/download-and-outlink/download-and-outlink.service.ts b/src/services/download-and-outlink/download-and-outlink.service.ts
index 7161afa..a38d45d 100644
--- a/src/services/download-and-outlink/download-and-outlink.service.ts
+++ b/src/services/download-and-outlink/download-and-outlink.service.ts
@@ -1,12 +1,14 @@
import { TRACK_EVENT } from '../../constants/track-event.constant';
+import { Tracker } from '../../interfaces/tracker';
+import { Dimensions } from '../../interfaces/utils';
import { PaqService } from '../paqService/paq.service';
-export function trackLink(url: string, linkType: string, customData?: object, callback?: (params: any) => void) {
+export function trackLink(url: string, linkType: string, dimensions?: Dimensions, callback?: () => void) {
PaqService.push([
TRACK_EVENT.LINK,
url,
linkType,
- customData,
+ dimensions,
callback
]);
}
@@ -39,11 +41,11 @@ export function setLinkTrackingTimer(time: number) {
PaqService.push([TRACK_EVENT.SET_LINK_TRACKING_TIMER, time]);
}
-export function getLinkTrackingTimer(): Promise {
+export function getLinkTrackingTimer(): Promise {
return new Promise((resolve, reject) => {
try {
PaqService.push([
- function (this: any) {
+ function (this: Tracker) {
resolve(this.getLinkTrackingTimer());
},
]);
diff --git a/src/services/e-commerce/e-commerce.service.ts b/src/services/e-commerce/e-commerce.service.ts
index 5d64bdc..64d3d79 100644
--- a/src/services/e-commerce/e-commerce.service.ts
+++ b/src/services/e-commerce/e-commerce.service.ts
@@ -2,6 +2,7 @@ import { TRACK_EVENT } from '../../constants/track-event.constant'
import { PaqService } from '../paqService/paq.service'
import { Product } from '../../interfaces/product'
import { PaymentInformation } from '../../interfaces/payment'
+import { Tracker } from '../../interfaces/tracker'
/**
* @deprecated since version 1.3.1. Please use the ecommerceAddToCart instead.
@@ -44,7 +45,7 @@ export function getEcommerceItems(): Promise