aesirx-analytics 1.0.6 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -9
- package/dist/index.js +5 -0
- package/package.json +12 -34
- package/src/AnalyticsNext/{handle.js → handle.tsx} +42 -10
- package/src/AnalyticsNext/index.tsx +26 -0
- package/src/AnalyticsReact/handle.tsx +72 -0
- package/src/AnalyticsReact/index.tsx +21 -0
- package/src/{analytics.js → analytics.ts} +15 -20
- package/src/{index.js → index.ts} +1 -1
- package/src/utils/AnalyticsContextProvider.tsx +57 -0
- package/src/utils/{index.js → index.ts} +32 -10
- package/src/utils/{services.js → services.ts} +3 -3
- package/build/analytics.js +0 -1
- package/build/lib/bundles/bundle.esm.min.js +0 -2
- package/build/lib/bundles/bundle.esm.min.js.map +0 -1
- package/build/lib/cjs/AnalyticsNext/handle.js +0 -119
- package/build/lib/cjs/AnalyticsNext/handle.js.map +0 -1
- package/build/lib/cjs/AnalyticsNext/index.js +0 -51
- package/build/lib/cjs/AnalyticsNext/index.js.map +0 -1
- package/build/lib/cjs/AnalyticsReact/handle.js +0 -77
- package/build/lib/cjs/AnalyticsReact/handle.js.map +0 -1
- package/build/lib/cjs/AnalyticsReact/index.js +0 -51
- package/build/lib/cjs/AnalyticsReact/index.js.map +0 -1
- package/build/lib/cjs/analytics.js +0 -197
- package/build/lib/cjs/analytics.js.map +0 -1
- package/build/lib/cjs/index.js +0 -35
- package/build/lib/cjs/index.js.map +0 -1
- package/build/lib/cjs/utils/AnalyticsContextProvider.js +0 -39
- package/build/lib/cjs/utils/AnalyticsContextProvider.js.map +0 -1
- package/build/lib/cjs/utils/index.js +0 -202
- package/build/lib/cjs/utils/index.js.map +0 -1
- package/build/lib/cjs/utils/services.js +0 -51
- package/build/lib/cjs/utils/services.js.map +0 -1
- package/build/lib/esm/AnalyticsNext/handle.js +0 -124
- package/build/lib/esm/AnalyticsNext/handle.js.map +0 -1
- package/build/lib/esm/AnalyticsNext/index.js +0 -56
- package/build/lib/esm/AnalyticsNext/index.js.map +0 -1
- package/build/lib/esm/AnalyticsReact/handle.js +0 -82
- package/build/lib/esm/AnalyticsReact/handle.js.map +0 -1
- package/build/lib/esm/AnalyticsReact/index.js +0 -56
- package/build/lib/esm/AnalyticsReact/index.js.map +0 -1
- package/build/lib/esm/analytics.js +0 -198
- package/build/lib/esm/analytics.js.map +0 -1
- package/build/lib/esm/index.js +0 -35
- package/build/lib/esm/index.js.map +0 -1
- package/build/lib/esm/utils/AnalyticsContextProvider.js +0 -45
- package/build/lib/esm/utils/AnalyticsContextProvider.js.map +0 -1
- package/build/lib/esm/utils/index.js +0 -206
- package/build/lib/esm/utils/index.js.map +0 -1
- package/build/lib/esm/utils/services.js +0 -54
- package/build/lib/esm/utils/services.js.map +0 -1
- package/build/lib/types/AnalyticsNext/handle.d.ts +0 -3
- package/build/lib/types/AnalyticsNext/handle.d.ts.map +0 -1
- package/build/lib/types/AnalyticsNext/index.d.ts +0 -3
- package/build/lib/types/AnalyticsNext/index.d.ts.map +0 -1
- package/build/lib/types/AnalyticsReact/handle.d.ts +0 -3
- package/build/lib/types/AnalyticsReact/handle.d.ts.map +0 -1
- package/build/lib/types/AnalyticsReact/index.d.ts +0 -3
- package/build/lib/types/AnalyticsReact/index.d.ts.map +0 -1
- package/build/lib/types/index.d.ts +0 -5
- package/build/lib/types/index.d.ts.map +0 -1
- package/build/lib/types/index.min.js +0 -1
- package/build/lib/types/utils/AnalyticsContextProvider.d.ts +0 -3
- package/build/lib/types/utils/AnalyticsContextProvider.d.ts.map +0 -1
- package/build/lib/types/utils/index.d.ts +0 -5
- package/build/lib/types/utils/index.d.ts.map +0 -1
- package/build/lib/types/utils/services.d.ts +0 -2
- package/build/lib/types/utils/services.d.ts.map +0 -1
- package/src/AnalyticsNext/index.js +0 -30
- package/src/AnalyticsReact/handle.js +0 -39
- package/src/AnalyticsReact/index.js +0 -29
- package/src/utils/AnalyticsContextProvider.js +0 -17
package/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# AesirX Analytics JS Collector
|
2
2
|
|
3
|
-
A powerful and compliant web Analytics platform (1st-party alternative to Google Analytics) that only collects 1st-party data to deliver meaningful customer insights for your organization.
|
3
|
+
A powerful and compliant web Analytics platform (1st-party alternative to Google Analytics) that only collects 1st-party data to deliver meaningful customer insights for your organization.
|
4
4
|
|
5
5
|
AesirX Analytics comes with a locally hosted JavaScript solution that gathers and stores data legally and compliantly in accordance with GDPR and other regional legislation including storage of citizens’ data in-country and 1st-party.
|
6
6
|
|
@@ -25,7 +25,6 @@ Follow the instructions in: [https://github.com/aesirxio/analytics-1stparty](htt
|
|
25
25
|
|
26
26
|
(`https://example.com` is the link to your 1st party server which must be installed)
|
27
27
|
|
28
|
-
|
29
28
|
#### Usage in ReactJS
|
30
29
|
|
31
30
|
`npm i aesirx-analytics`
|
@@ -44,18 +43,20 @@ Create AnalyticsContainer component:
|
|
44
43
|
|
45
44
|
```
|
46
45
|
import React from 'react';
|
47
|
-
import { useLocation } from 'react-router-dom';
|
46
|
+
import { useLocation, useHistory } from 'react-router-dom';
|
48
47
|
import { AnalyticsReact } from 'aesirx-analytics';
|
49
48
|
const AnalyticsContainer = ({children}) => {
|
50
49
|
const location = useLocation();
|
51
|
-
|
50
|
+
let history = useHistory();
|
51
|
+
return <AnalyticsReact location={location} history={history}>{children}</AnalyticsReact>;
|
52
52
|
};
|
53
53
|
|
54
54
|
export default AnalyticsContainer;
|
55
55
|
```
|
56
56
|
|
57
57
|
###### Wrap your component in `<AnalyticsContainer><[YOUR-COMPONENT]/></AnalyticsContainer>`
|
58
|
-
|
58
|
+
|
59
|
+
###### `<AnalyticsContainer>` need to using inside `<Router>` component
|
59
60
|
|
60
61
|
#### Usage in NextJS
|
61
62
|
|
@@ -85,10 +86,12 @@ import { AnalyticsNext } from "aesirx-analytics";
|
|
85
86
|
## Track events:
|
86
87
|
|
87
88
|
#### In SSR Site:
|
89
|
+
|
88
90
|
To track events, simply add special data-attribute to the element you want to track.
|
89
91
|
For example, you might have a button with the following code:
|
92
|
+
|
90
93
|
```
|
91
|
-
<button class="button"
|
94
|
+
<button class="button"
|
92
95
|
data-aesirx-event-name="sign up"
|
93
96
|
data-aesirx-event-type="login"
|
94
97
|
data-aesirx-event-attribute-a="value-a"
|
@@ -97,17 +100,22 @@ For example, you might have a button with the following code:
|
|
97
100
|
Sign Up
|
98
101
|
</button>
|
99
102
|
```
|
103
|
+
|
100
104
|
Add data-attribute with the following format:
|
105
|
+
|
101
106
|
```
|
102
107
|
data-aesirx-event-name="<event-name>"
|
103
108
|
data-aesirx-event-type="<event-type>"
|
104
109
|
data-aesirx-event-attribute-<attribute-name-1>="<attribute-value-1>"
|
105
110
|
data-aesirx-event-attribute-<attribute-name-2>="<attribute-value-1>"
|
106
111
|
```
|
112
|
+
|
107
113
|
##### Or you can use your own Javascript to Track events:
|
114
|
+
|
108
115
|
```
|
109
116
|
window.trackEvent(endpoint, event_uuid, visitor_uuid, referrer, data)
|
110
117
|
```
|
118
|
+
|
111
119
|
(`endpoint` is the link to your 1st party server which must be installed)
|
112
120
|
|
113
121
|
(`event_uuid` is the params get from url - it will auto generated)
|
@@ -118,12 +126,13 @@ window.trackEvent(endpoint, event_uuid, visitor_uuid, referrer, data)
|
|
118
126
|
|
119
127
|
(`data` is the data you want to track)
|
120
128
|
|
121
|
-
For example:
|
129
|
+
For example:
|
130
|
+
|
122
131
|
```
|
123
132
|
trackEvent(
|
124
133
|
"https://example.com",
|
125
|
-
event_uuid,
|
126
|
-
visitor_uuid,
|
134
|
+
event_uuid,
|
135
|
+
visitor_uuid,
|
127
136
|
"https://aesirx.io",
|
128
137
|
{
|
129
138
|
event_name: "<event_name>",
|
package/dist/index.js
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
var O=Object.create;var A=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var Q=Object.getOwnPropertyNames;var Y=Object.getPrototypeOf,F=Object.prototype.hasOwnProperty;var J=(t,i)=>{for(var e in i)A(t,e,{get:i[e],enumerable:!0})},T=(t,i,e,n)=>{if(i&&typeof i=="object"||typeof i=="function")for(let s of Q(i))!F.call(t,s)&&s!==e&&A(t,s,{get:()=>i[s],enumerable:!(n=B(i,s))||n.enumerable});return t};var g=(t,i,e)=>(e=t!=null?O(Y(t)):{},T(i||!t||!t.__esModule?A(e,"default",{value:t,enumerable:!0}):e,t)),W=t=>T(A({},"__esModule",{value:!0}),t);var Z={};J(Z,{AnalyticsContext:()=>m,AnalyticsNext:()=>L,AnalyticsReact:()=>j,trackEvent:()=>q});module.exports=W(Z);var w=g(require("react"));var l=g(require("react"));var m=l.default.createContext({event_uuid:void 0,visitor_uuid:void 0,event_uuid_start:void 0,visitor_uuid_start:void 0,setEventID:void 0,setUUID:void 0,setEventIDStart:void 0,setUUIDStart:void 0}),P=({children:t})=>{let[i,e]=(0,l.useState)(),[n,s]=(0,l.useState)(),[a,d]=(0,l.useState)(),[u,r]=(0,l.useState)();return l.default.createElement(m.Provider,{value:{event_uuid:i,visitor_uuid:n,event_uuid_start:a,visitor_uuid_start:u,setEventID:e,setUUID:s,setEventIDStart:d,setUUIDStart:r}},t)};var v=g(require("react"));var X,z=(t,i)=>(Object.keys(i).forEach(e=>{i[e]!==void 0&&(t[e]=i[e])}),t),y=async(t,i)=>await(await fetch(t,{method:"POST",body:JSON.stringify(i),headers:z({"Content-Type":"application/json"},{["x-tracker-cache"]:X})})).json();var k=g(require("bowser")),U=(t,i)=>`${t}/visitor/v1/${i}`,D=async(t,i,e,n)=>{let{document:s}=window,{pathname:a,search:d,origin:u}=location;i=`${u}${a}${d}`,e=s.referrer,n=window.navigator.userAgent;let r=k.default.parse(window.navigator.userAgent),o=r?.browser?.name,_=r?.browser?.version,c=window.navigator.userLanguage||window.navigator.language,E=r?.platform?.model??r?.platform?.type,C=`${u}`,$=window.location.search,f=new URLSearchParams($),N=[];for(let h of f.keys())h.startsWith("utm_")&&f.get(h)&&N.push({name:h,value:f.get(h)});if(!f.get("event_uuid")&&!f.get("visitor_uuid")){let h="";return await y(U(t,"init"),{url:i,referrer:e,user_agent:n,ip:h,domain:C,browser_name:o,browser_version:_,lang:c,device:E,event_name:"visit",event_type:"action",attributes:N})}},I=async(t,i,e,n)=>{let{location:s,document:a}=window;n=n?s.protocol+"//"+s.host+n:a.referrer.split("?")[0];let d=s.protocol+"//"+s.host+s.pathname,u=window.location.search,r=new URLSearchParams(u);return await y(U(t,"start"),{...r.get("event_uuid")&&{event_uuid:r.get("event_uuid")},...r.get("visitor_uuid")&&{visitor_uuid:r.get("visitor_uuid")},...i&&{event_uuid:i},...e&&{visitor_uuid:e},referrer:n==="/"?"":n,url:d})},x=async(t,i,e)=>{let n=window.location.search,s=new URLSearchParams(n);return await y(U(t,"end"),{...s.get("event_uuid_start")&&{event_uuid:s.get("event_uuid_start")},...s.get("visitor_uuid_start")&&{visitor_uuid:s.get("visitor_uuid_start")},...i&&{event_uuid:i},...e&&{visitor_uuid:e}})},q=async(t,i,e,n,s)=>{let{location:a,document:d}=window;n=n?a.protocol+"//"+a.host+n:d.referrer.split("?")[0];let u=a.protocol+"//"+a.host+a.pathname,r=window.location.search,o=new URLSearchParams(r);return await y(U(t,"start"),{...o.get("event_uuid")&&{event_uuid:o.get("event_uuid")},...o.get("visitor_uuid")&&{visitor_uuid:o.get("visitor_uuid")},...i&&{event_uuid:i},...e&&{visitor_uuid:e},referrer:n==="/"?"":n,url:u,...s})};var G=({router:t,children:i})=>{let e=v.default.useContext(m),n=process.env.NEXT_PUBLIC_ENDPOINT_ANALYTICS_URL,[s,a]=(0,v.useState)(t.asPath),d=(0,v.useCallback)(async u=>{let r=u||"",o=await I(n,e.event_uuid,e.visitor_uuid,r);o.event_uuid&&e.setEventIDStart(o.event_uuid),o.visitor_uuid&&e.setUUIDStart(o.visitor_uuid)},[e,n]);return(0,v.useEffect)(()=>{(async()=>{let r=new URLSearchParams(window.location.search),o=r.get("event_uuid"),_=r.get("visitor_uuid");if(!e.event_uuid&&!e.visitor_uuid)if(o&&_)e.setEventID(o),e.setUUID(_);else{let c=await D(n);c?.event_uuid&&e.setEventID(c?.event_uuid),e.setUUID(c?.visitor_uuid)}else await d(s)})()},[e.visitor_uuid]),(0,v.useEffect)(()=>{let u=async()=>{let{event_uuid:r,visitor_uuid:o}=t.query;e.visitor_uuid_start&&!r&&!o&&(await x(n,e.event_uuid_start,e.visitor_uuid_start),await d(s)),a(t.asPath)};return t.events.on("routeChangeComplete",u),t.replace({query:{...t.query,event_uuid:e.event_uuid,visitor_uuid:e.visitor_uuid}},void 0,{shallow:!0}),()=>{t.events.off("routeChangeComplete",u)}},[t.events,e.visitor_uuid_start,t.asPath]),v.default.createElement(v.default.Fragment,null,i)},b=G;var K=({router:t,children:i})=>w.default.createElement(w.default.Fragment,null,w.default.createElement(P,null,w.default.createElement(b,{router:t},i))),L=K;var R=g(require("react"));var p=g(require("react")),S=g(require("query-string"));var M=({location:t,history:i,children:e})=>{let n=p.default.useContext(m),s=process.env.REACT_APP_ENDPOINT_ANALYTICS_URL,[a,d]=(0,p.useState)(null);return(0,p.useEffect)(()=>{(async()=>{if(n.visitor_uuid_start&&await x(s,n.event_uuid_start,n.visitor_uuid_start),!n.event_uuid&&!n.visitor_uuid){let r=new URLSearchParams(window.location.search),o=r.get("event_uuid"),_=r.get("visitor_uuid");if(o&&_)n.setEventID(o),n.setUUID(_);else{let c=await D(s);c.event_uuid&&n.setEventID(c.event_uuid),n.setUUID(c.visitor_uuid);let C={...S.default.parse(t.search),event_uuid:c.event_uuid,visitor_uuid:c.visitor_uuid};i.push({search:S.default.stringify(C)})}}else{let o={...S.default.parse(t.search),event_uuid:n.event_uuid,visitor_uuid:n.visitor_uuid};i.push({search:S.default.stringify(o)});let _=a||"",c=await I(s,n.event_uuid,n.visitor_uuid,_);c.event_uuid&&n.setEventIDStart(c.event_uuid),c.visitor_uuid&&n.setUUIDStart(c.visitor_uuid),d(t.pathname)}})()},[t.pathname,n.visitor_uuid,i]),p.default.createElement(p.default.Fragment,null,e)},H=M;var V=({location:t,history:i,children:e})=>R.default.createElement(P,null,R.default.createElement(H,{location:t,history:i},e)),j=V;0&&(module.exports={AnalyticsContext,AnalyticsNext,AnalyticsReact,trackEvent});
|
2
|
+
/*
|
3
|
+
* @copyright Copyright (C) 2022 AesirX. All rights reserved.
|
4
|
+
* @license GNU General Public License version 3, see LICENSE.
|
5
|
+
*/
|
package/package.json
CHANGED
@@ -1,31 +1,17 @@
|
|
1
1
|
{
|
2
2
|
"name": "aesirx-analytics",
|
3
|
-
"version": "1.0
|
3
|
+
"version": "1.1.0",
|
4
4
|
"license": "GPL-3.0-only",
|
5
5
|
"author": "AesirX",
|
6
6
|
"repository": "https://gitlab.redweb.dk/aesirx/analytics",
|
7
|
-
"main": "
|
8
|
-
"module": "build/lib/esm/index.js",
|
9
|
-
"exports": {
|
10
|
-
"require": "./build/lib/cjs/index.js",
|
11
|
-
"import": "./build/lib/esm/index.js"
|
12
|
-
},
|
13
|
-
"types": "build/lib/types/index.d.ts",
|
14
|
-
"source": "src/index.js",
|
7
|
+
"main": "dist/index.js",
|
15
8
|
"dependencies": {
|
16
9
|
"bowser": "^2.11.0",
|
17
|
-
"
|
18
|
-
"dotenv": "^16.0.3",
|
19
|
-
"npm-run-all": "^4.1.5",
|
20
|
-
"public-ip": "^6.0.1",
|
21
|
-
"rimraf": "^3.0.2"
|
10
|
+
"query-string": "^7.1.1"
|
22
11
|
},
|
23
12
|
"scripts": {
|
24
13
|
"clean": "rimraf lib",
|
25
|
-
"build
|
26
|
-
"build:cjs": "cross-env BABEL_ENV=cjs babel src --extensions '.js' --out-dir 'build/lib/cjs' --source-maps",
|
27
|
-
"build:bundles": "cross-env BABEL_ENV=esmBundled rollup -c",
|
28
|
-
"build": "npm-run-all -l clean -p build:esm build:cjs build:bundles",
|
14
|
+
"build": "tsup",
|
29
15
|
"lint": "eslint --fix \"src/**/\"",
|
30
16
|
"lint:check": "eslint \"src/**/\"",
|
31
17
|
"lint:nowarns": "eslint --quiet \"src/**/\"",
|
@@ -56,24 +42,16 @@
|
|
56
42
|
"react-dom": "^17.0.1"
|
57
43
|
},
|
58
44
|
"devDependencies": {
|
59
|
-
"@
|
60
|
-
"@
|
61
|
-
"@
|
62
|
-
"@
|
63
|
-
"@
|
64
|
-
"
|
65
|
-
"@rollup/plugin-babel": "^6.0.2",
|
66
|
-
"@rollup/plugin-json": "^6.0.0",
|
67
|
-
"@rollup/plugin-commonjs": "^24.0.1",
|
68
|
-
"@rollup/plugin-node-resolve": "^15.0.1",
|
69
|
-
"@rollup/plugin-replace": "^4.0.0",
|
70
|
-
"babel-plugin-module-resolver": "^5.0.0",
|
71
|
-
"eslint": "^8.34",
|
45
|
+
"@types/node": "^18.15.11",
|
46
|
+
"@types/react": "^18.0.30",
|
47
|
+
"@types/react-dom": "^18.0.11",
|
48
|
+
"@typescript-eslint/eslint-plugin": "^5.57.0",
|
49
|
+
"@typescript-eslint/parser": "^5.57.0",
|
50
|
+
"eslint": "^8.36",
|
72
51
|
"eslint-plugin-react": "^7.31.10",
|
73
52
|
"prettier": "^2.8.4",
|
74
|
-
"
|
75
|
-
"
|
76
|
-
"rollup-plugin-typescript2": "^0.34.1",
|
53
|
+
"rimraf": "^4.4.1",
|
54
|
+
"tsup": "^6.7.0",
|
77
55
|
"typescript": "^4.9.3"
|
78
56
|
},
|
79
57
|
"overrides": {
|
@@ -1,13 +1,24 @@
|
|
1
|
-
import React, { useCallback, useEffect, useState } from 'react';
|
1
|
+
import React, { ReactNode, useCallback, useEffect, useState } from 'react';
|
2
2
|
import { AnalyticsContext } from '../utils/AnalyticsContextProvider';
|
3
3
|
import { initTracker, startTracker, endTracker } from '../utils/index';
|
4
4
|
|
5
|
-
|
5
|
+
interface AnalyticsHandle {
|
6
|
+
router: {
|
7
|
+
asPath: string;
|
8
|
+
events: { on: (_: string, __: () => void) => void; off: (_: string, __: () => void) => void };
|
9
|
+
replace: any;
|
10
|
+
query: any;
|
11
|
+
push: any;
|
12
|
+
};
|
13
|
+
children?: ReactNode;
|
14
|
+
}
|
15
|
+
|
16
|
+
const AnalyticsHandle = ({ router, children }: AnalyticsHandle) => {
|
6
17
|
const AnalyticsStore = React.useContext(AnalyticsContext);
|
7
18
|
const endPoint = process.env.NEXT_PUBLIC_ENDPOINT_ANALYTICS_URL;
|
8
|
-
const [prevRoute, setPrevRoute] = useState(router.asPath);
|
19
|
+
const [prevRoute, setPrevRoute] = useState<string>(router.asPath);
|
9
20
|
const handleStartTracker = useCallback(
|
10
|
-
async (prevRoute) => {
|
21
|
+
async (prevRoute: string) => {
|
11
22
|
const referrer = prevRoute ? prevRoute : '';
|
12
23
|
const responseStart = await startTracker(
|
13
24
|
endPoint,
|
@@ -23,12 +34,20 @@ const AnalyticsHandle = ({ router, children }) => {
|
|
23
34
|
|
24
35
|
useEffect(() => {
|
25
36
|
const init = async () => {
|
37
|
+
const urlParams = new URLSearchParams(window.location.search);
|
38
|
+
const event_uuid = urlParams.get('event_uuid');
|
39
|
+
const visitor_uuid = urlParams.get('visitor_uuid');
|
26
40
|
if (!AnalyticsStore.event_uuid && !AnalyticsStore.visitor_uuid) {
|
27
|
-
|
28
|
-
|
29
|
-
|
41
|
+
if (event_uuid && visitor_uuid) {
|
42
|
+
AnalyticsStore.setEventID(event_uuid);
|
43
|
+
AnalyticsStore.setUUID(visitor_uuid);
|
44
|
+
} else {
|
45
|
+
const responseInit = await initTracker(endPoint);
|
46
|
+
responseInit?.event_uuid && AnalyticsStore.setEventID(responseInit?.event_uuid);
|
47
|
+
AnalyticsStore.setUUID(responseInit?.visitor_uuid);
|
48
|
+
}
|
30
49
|
} else {
|
31
|
-
await handleStartTracker();
|
50
|
+
await handleStartTracker(prevRoute);
|
32
51
|
}
|
33
52
|
};
|
34
53
|
init();
|
@@ -36,7 +55,8 @@ const AnalyticsHandle = ({ router, children }) => {
|
|
36
55
|
|
37
56
|
useEffect(() => {
|
38
57
|
const handleRouteChange = async () => {
|
39
|
-
|
58
|
+
const { event_uuid, visitor_uuid } = router.query;
|
59
|
+
if (AnalyticsStore.visitor_uuid_start && !event_uuid && !visitor_uuid) {
|
40
60
|
await endTracker(
|
41
61
|
endPoint,
|
42
62
|
AnalyticsStore.event_uuid_start,
|
@@ -47,7 +67,19 @@ const AnalyticsHandle = ({ router, children }) => {
|
|
47
67
|
setPrevRoute(router.asPath);
|
48
68
|
};
|
49
69
|
router.events.on('routeChangeComplete', handleRouteChange);
|
50
|
-
|
70
|
+
router.replace(
|
71
|
+
{
|
72
|
+
query: {
|
73
|
+
...router.query,
|
74
|
+
event_uuid: AnalyticsStore.event_uuid,
|
75
|
+
visitor_uuid: AnalyticsStore.visitor_uuid,
|
76
|
+
},
|
77
|
+
},
|
78
|
+
undefined,
|
79
|
+
{
|
80
|
+
shallow: true,
|
81
|
+
}
|
82
|
+
);
|
51
83
|
return () => {
|
52
84
|
router.events.off('routeChangeComplete', handleRouteChange);
|
53
85
|
};
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import React, { ReactNode } from 'react';
|
2
|
+
|
3
|
+
import { AnalyticsContextProvider } from '../utils/AnalyticsContextProvider';
|
4
|
+
import AnalyticsHandle from './handle';
|
5
|
+
|
6
|
+
interface AnalyticsReact {
|
7
|
+
router: {
|
8
|
+
asPath: string;
|
9
|
+
events: { on: (_: string, __: () => void) => void; off: (_: string, __: () => void) => void };
|
10
|
+
replace: any;
|
11
|
+
query: any;
|
12
|
+
push: any;
|
13
|
+
};
|
14
|
+
children?: ReactNode;
|
15
|
+
}
|
16
|
+
|
17
|
+
const AnalyticsNext = ({ router, children }: AnalyticsReact) => {
|
18
|
+
return (
|
19
|
+
<>
|
20
|
+
<AnalyticsContextProvider>
|
21
|
+
<AnalyticsHandle router={router}>{children}</AnalyticsHandle>
|
22
|
+
</AnalyticsContextProvider>
|
23
|
+
</>
|
24
|
+
);
|
25
|
+
};
|
26
|
+
export default AnalyticsNext;
|
@@ -0,0 +1,72 @@
|
|
1
|
+
import React, { ReactNode, useEffect, useState } from 'react';
|
2
|
+
import qs from 'query-string';
|
3
|
+
import { AnalyticsContext } from '../utils/AnalyticsContextProvider';
|
4
|
+
import { initTracker, startTracker, endTracker } from '../utils/index';
|
5
|
+
|
6
|
+
interface AnalyticsHandle {
|
7
|
+
location: { search: string; pathname: string };
|
8
|
+
history: { push: (_: object) => void };
|
9
|
+
children?: ReactNode;
|
10
|
+
}
|
11
|
+
|
12
|
+
const AnalyticsHandle = ({ location, history, children }: AnalyticsHandle) => {
|
13
|
+
const AnalyticsStore = React.useContext(AnalyticsContext);
|
14
|
+
const endPoint = process.env.REACT_APP_ENDPOINT_ANALYTICS_URL;
|
15
|
+
const [prevRoute, setPrevRoute] = useState<string>(null);
|
16
|
+
useEffect(() => {
|
17
|
+
const init = async () => {
|
18
|
+
if (AnalyticsStore.visitor_uuid_start) {
|
19
|
+
await endTracker(
|
20
|
+
endPoint,
|
21
|
+
AnalyticsStore.event_uuid_start,
|
22
|
+
AnalyticsStore.visitor_uuid_start
|
23
|
+
);
|
24
|
+
}
|
25
|
+
if (!AnalyticsStore.event_uuid && !AnalyticsStore.visitor_uuid) {
|
26
|
+
const urlParams = new URLSearchParams(window.location.search);
|
27
|
+
const event_uuid = urlParams.get('event_uuid');
|
28
|
+
const visitor_uuid = urlParams.get('visitor_uuid');
|
29
|
+
if (event_uuid && visitor_uuid) {
|
30
|
+
AnalyticsStore.setEventID(event_uuid);
|
31
|
+
AnalyticsStore.setUUID(visitor_uuid);
|
32
|
+
} else {
|
33
|
+
const responseInit = await initTracker(endPoint);
|
34
|
+
responseInit.event_uuid && AnalyticsStore.setEventID(responseInit.event_uuid);
|
35
|
+
AnalyticsStore.setUUID(responseInit.visitor_uuid);
|
36
|
+
// Add Params to URL
|
37
|
+
const queryParams = qs.parse(location.search);
|
38
|
+
const newQueries = {
|
39
|
+
...queryParams,
|
40
|
+
event_uuid: responseInit.event_uuid,
|
41
|
+
visitor_uuid: responseInit.visitor_uuid,
|
42
|
+
};
|
43
|
+
history.push({ search: qs.stringify(newQueries) });
|
44
|
+
}
|
45
|
+
} else {
|
46
|
+
// Add Params to URL
|
47
|
+
const queryParams = qs.parse(location.search);
|
48
|
+
const newQueries = {
|
49
|
+
...queryParams,
|
50
|
+
event_uuid: AnalyticsStore.event_uuid,
|
51
|
+
visitor_uuid: AnalyticsStore.visitor_uuid,
|
52
|
+
};
|
53
|
+
history.push({ search: qs.stringify(newQueries) });
|
54
|
+
|
55
|
+
const referrer = prevRoute ? prevRoute : '';
|
56
|
+
const responseStart = await startTracker(
|
57
|
+
endPoint,
|
58
|
+
AnalyticsStore.event_uuid,
|
59
|
+
AnalyticsStore.visitor_uuid,
|
60
|
+
referrer
|
61
|
+
);
|
62
|
+
responseStart.event_uuid && AnalyticsStore.setEventIDStart(responseStart.event_uuid);
|
63
|
+
responseStart.visitor_uuid && AnalyticsStore.setUUIDStart(responseStart.visitor_uuid);
|
64
|
+
setPrevRoute(location.pathname);
|
65
|
+
}
|
66
|
+
};
|
67
|
+
init();
|
68
|
+
}, [location.pathname, AnalyticsStore.visitor_uuid, history]);
|
69
|
+
|
70
|
+
return <>{children}</>;
|
71
|
+
};
|
72
|
+
export default AnalyticsHandle;
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import React, { ReactNode } from 'react';
|
2
|
+
|
3
|
+
import { AnalyticsContextProvider } from '../utils/AnalyticsContextProvider';
|
4
|
+
import AnalyticsHandle from './handle';
|
5
|
+
|
6
|
+
interface AnalyticsReact {
|
7
|
+
location: { search: string; pathname: string };
|
8
|
+
history: { push: (_: object) => void };
|
9
|
+
children?: ReactNode;
|
10
|
+
}
|
11
|
+
|
12
|
+
const AnalyticsReact = ({ location, history, children }: AnalyticsReact) => {
|
13
|
+
return (
|
14
|
+
<AnalyticsContextProvider>
|
15
|
+
<AnalyticsHandle location={location} history={history}>
|
16
|
+
{children}
|
17
|
+
</AnalyticsHandle>
|
18
|
+
</AnalyticsContextProvider>
|
19
|
+
);
|
20
|
+
};
|
21
|
+
export default AnalyticsReact;
|
@@ -1,10 +1,10 @@
|
|
1
|
-
import { endTracker, initTracker, startTracker, trackEvent } from './utils';
|
1
|
+
import { endTracker, initTracker, insertParam, startTracker, trackEvent } from './utils';
|
2
2
|
|
3
3
|
const AesirAnalytics = () => {
|
4
|
-
const hook = (_this, method, callback) => {
|
4
|
+
const hook = (_this: object, method: string, callback: (_: string) => void) => {
|
5
5
|
const orig = _this[method];
|
6
6
|
|
7
|
-
return (...args) => {
|
7
|
+
return (...args: []) => {
|
8
8
|
callback.apply(null, args);
|
9
9
|
|
10
10
|
return orig.apply(_this, args);
|
@@ -13,7 +13,7 @@ const AesirAnalytics = () => {
|
|
13
13
|
|
14
14
|
/* Handle history changes */
|
15
15
|
|
16
|
-
const handlePush = async (url) => {
|
16
|
+
const handlePush = async (url: string) => {
|
17
17
|
if (!url) return;
|
18
18
|
const { pathname, search, origin } = location;
|
19
19
|
url = `${origin}${pathname}${search}`;
|
@@ -33,12 +33,12 @@ const AesirAnalytics = () => {
|
|
33
33
|
|
34
34
|
/* Global */
|
35
35
|
|
36
|
-
if (!window
|
37
|
-
const tracker = (eventValue) => eventValue;
|
36
|
+
if (!window['tracker']) {
|
37
|
+
const tracker = (eventValue: string) => eventValue;
|
38
38
|
tracker.initTracker = initTracker;
|
39
39
|
tracker.startTracker = startTracker;
|
40
40
|
|
41
|
-
window
|
41
|
+
window['tracker'] = tracker;
|
42
42
|
}
|
43
43
|
|
44
44
|
/* Start */
|
@@ -46,7 +46,7 @@ const AesirAnalytics = () => {
|
|
46
46
|
history.pushState = hook(history, 'pushState', handlePush);
|
47
47
|
history.replaceState = hook(history, 'replaceState', handlePush);
|
48
48
|
|
49
|
-
const hostUrl = window
|
49
|
+
const hostUrl = window['aesirx1stparty'] ? window['aesirx1stparty'] : '';
|
50
50
|
|
51
51
|
const root = hostUrl ? hostUrl.replace(/\/$/, '') : '';
|
52
52
|
|
@@ -87,16 +87,16 @@ const AesirAnalytics = () => {
|
|
87
87
|
|
88
88
|
/* Handle events */
|
89
89
|
|
90
|
-
const addEvents = (node) => {
|
90
|
+
const addEvents = (node: Document) => {
|
91
91
|
const elements = node.querySelectorAll(eventSelect);
|
92
92
|
Array.prototype.forEach.call(elements, addEvent);
|
93
93
|
};
|
94
94
|
|
95
|
-
const addEvent = (element) => {
|
95
|
+
const addEvent = (element: HTMLInputElement) => {
|
96
96
|
element.addEventListener(
|
97
97
|
'click',
|
98
98
|
() => {
|
99
|
-
|
99
|
+
const attribute: object[] = [];
|
100
100
|
Object.keys(element.dataset).forEach((key) => {
|
101
101
|
if (key.startsWith('aesirxEventAttribute')) {
|
102
102
|
attribute.push({
|
@@ -105,7 +105,7 @@ const AesirAnalytics = () => {
|
|
105
105
|
});
|
106
106
|
}
|
107
107
|
});
|
108
|
-
trackEvent(root,
|
108
|
+
trackEvent(root, '', '', '', {
|
109
109
|
event_name: element.dataset.aesirxEventName,
|
110
110
|
event_type: element.dataset.aesirxEventType,
|
111
111
|
attributes: attribute,
|
@@ -117,18 +117,13 @@ const AesirAnalytics = () => {
|
|
117
117
|
|
118
118
|
update();
|
119
119
|
};
|
120
|
-
const insertParam = (key, value) => {
|
121
|
-
const url = new URL(window.location.href);
|
122
|
-
url.searchParams.set(key, value);
|
123
|
-
window.history.pushState({ path: url.href }, '', url.href);
|
124
|
-
};
|
125
120
|
|
126
121
|
const replaceUrl = () => {
|
127
122
|
const urlParams = new URLSearchParams(window.location.search);
|
128
123
|
const event_uuid = urlParams.get('event_uuid');
|
129
124
|
const visitor_uuid = urlParams.get('visitor_uuid');
|
130
125
|
|
131
|
-
|
126
|
+
const anchors = document.getElementsByTagName('a');
|
132
127
|
|
133
128
|
for (let i = 0; i < anchors.length; i++) {
|
134
129
|
const eventIdParams = getParameterByName('event_uuid', anchors[i].href);
|
@@ -142,9 +137,9 @@ const replaceUrl = () => {
|
|
142
137
|
}
|
143
138
|
};
|
144
139
|
|
145
|
-
const getParameterByName = (name, url = window.location.href) => {
|
140
|
+
const getParameterByName = (name: string, url = window.location.href) => {
|
146
141
|
if (url) {
|
147
|
-
|
142
|
+
const params = new URL(url);
|
148
143
|
if (params.origin === window.location.origin) {
|
149
144
|
return params.searchParams.get(name);
|
150
145
|
}
|
@@ -1,4 +1,4 @@
|
|
1
1
|
export { default as AnalyticsNext } from './AnalyticsNext';
|
2
2
|
export { default as AnalyticsReact } from './AnalyticsReact';
|
3
|
-
export { trackEvent } from './utils
|
3
|
+
export { trackEvent } from './utils';
|
4
4
|
export { AnalyticsContext } from './utils/AnalyticsContextProvider';
|
@@ -0,0 +1,57 @@
|
|
1
|
+
/*
|
2
|
+
* @copyright Copyright (C) 2022 AesirX. All rights reserved.
|
3
|
+
* @license GNU General Public License version 3, see LICENSE.
|
4
|
+
*/
|
5
|
+
|
6
|
+
import React, { Dispatch, ReactNode, SetStateAction, useState } from 'react';
|
7
|
+
|
8
|
+
interface Props {
|
9
|
+
children?: ReactNode;
|
10
|
+
}
|
11
|
+
|
12
|
+
interface AnalyticsContextType {
|
13
|
+
event_uuid: string;
|
14
|
+
visitor_uuid: string;
|
15
|
+
event_uuid_start: string;
|
16
|
+
visitor_uuid_start: string;
|
17
|
+
setEventID: Dispatch<SetStateAction<string>>;
|
18
|
+
setUUID: Dispatch<SetStateAction<string>>;
|
19
|
+
setEventIDStart: Dispatch<SetStateAction<string>>;
|
20
|
+
setUUIDStart: Dispatch<SetStateAction<string>>;
|
21
|
+
}
|
22
|
+
|
23
|
+
export const AnalyticsContext = React.createContext<AnalyticsContextType>({
|
24
|
+
event_uuid: undefined,
|
25
|
+
visitor_uuid: undefined,
|
26
|
+
event_uuid_start: undefined,
|
27
|
+
visitor_uuid_start: undefined,
|
28
|
+
setEventID: undefined,
|
29
|
+
setUUID: undefined,
|
30
|
+
setEventIDStart: undefined,
|
31
|
+
setUUIDStart: undefined,
|
32
|
+
});
|
33
|
+
|
34
|
+
const AnalyticsContextProvider: React.FC<Props> = ({ children }) => {
|
35
|
+
const [eventID, setEventID] = useState();
|
36
|
+
const [UUID, setUUID] = useState();
|
37
|
+
const [eventIDStart, setEventIDStart] = useState();
|
38
|
+
const [UUIDStart, setUUIDStart] = useState();
|
39
|
+
return (
|
40
|
+
<AnalyticsContext.Provider
|
41
|
+
value={{
|
42
|
+
event_uuid: eventID,
|
43
|
+
visitor_uuid: UUID,
|
44
|
+
event_uuid_start: eventIDStart,
|
45
|
+
visitor_uuid_start: UUIDStart,
|
46
|
+
setEventID: setEventID,
|
47
|
+
setUUID: setUUID,
|
48
|
+
setEventIDStart: setEventIDStart,
|
49
|
+
setUUIDStart: setUUIDStart,
|
50
|
+
}}
|
51
|
+
>
|
52
|
+
{children}
|
53
|
+
</AnalyticsContext.Provider>
|
54
|
+
);
|
55
|
+
};
|
56
|
+
|
57
|
+
export { AnalyticsContextProvider };
|
@@ -1,12 +1,17 @@
|
|
1
1
|
import { trackerService } from './services';
|
2
2
|
import Bowser from 'bowser';
|
3
3
|
|
4
|
-
const createRequest = (endpoint, task) => {
|
4
|
+
const createRequest = (endpoint: string, task: string) => {
|
5
5
|
return `${endpoint}/visitor/v1/${task}`;
|
6
6
|
};
|
7
7
|
|
8
8
|
/* FUNCTION */
|
9
|
-
const initTracker = async (
|
9
|
+
const initTracker = async (
|
10
|
+
endpoint: string,
|
11
|
+
url?: string,
|
12
|
+
referrer?: string,
|
13
|
+
user_agent?: string
|
14
|
+
) => {
|
10
15
|
const { document } = window;
|
11
16
|
const { pathname, search, origin } = location;
|
12
17
|
url = `${origin}${pathname}${search}`;
|
@@ -15,19 +20,19 @@ const initTracker = async (endpoint, url, referrer, user_agent) => {
|
|
15
20
|
const browser = Bowser.parse(window.navigator.userAgent);
|
16
21
|
const browser_name = browser?.browser?.name;
|
17
22
|
const browser_version = browser?.browser?.version;
|
18
|
-
const lang = window.navigator
|
23
|
+
const lang = window.navigator['userLanguage'] || window.navigator.language;
|
19
24
|
const device = browser?.platform?.model ?? browser?.platform?.type;
|
20
25
|
const domain = `${origin}`;
|
21
26
|
const queryString = window.location.search;
|
22
27
|
const urlParams = new URLSearchParams(queryString);
|
23
|
-
|
24
|
-
for (
|
28
|
+
const attributes = [];
|
29
|
+
for (const key of urlParams.keys()) {
|
25
30
|
if (key.startsWith('utm_')) {
|
26
31
|
urlParams.get(key) && attributes.push({ name: key, value: urlParams.get(key) });
|
27
32
|
}
|
28
33
|
}
|
29
34
|
if (!urlParams.get('event_uuid') && !urlParams.get('visitor_uuid')) {
|
30
|
-
|
35
|
+
const ip = '';
|
31
36
|
const response = await trackerService(createRequest(endpoint, 'init'), {
|
32
37
|
url: url,
|
33
38
|
referrer: referrer,
|
@@ -46,7 +51,12 @@ const initTracker = async (endpoint, url, referrer, user_agent) => {
|
|
46
51
|
}
|
47
52
|
};
|
48
53
|
|
49
|
-
const startTracker = async (
|
54
|
+
const startTracker = async (
|
55
|
+
endpoint: string,
|
56
|
+
event_uuid?: string,
|
57
|
+
visitor_uuid?: string,
|
58
|
+
referrer?: string
|
59
|
+
) => {
|
50
60
|
const { location, document } = window;
|
51
61
|
referrer = referrer
|
52
62
|
? location.protocol + '//' + location.host + referrer
|
@@ -74,7 +84,7 @@ const startTracker = async (endpoint, event_uuid, visitor_uuid, referrer) => {
|
|
74
84
|
return responseStart;
|
75
85
|
};
|
76
86
|
|
77
|
-
const endTracker = async (endpoint, event_uuid, visitor_uuid) => {
|
87
|
+
const endTracker = async (endpoint: string, event_uuid?: string, visitor_uuid?: string) => {
|
78
88
|
const queryString = window.location.search;
|
79
89
|
const urlParams = new URLSearchParams(queryString);
|
80
90
|
const responseEnd = await trackerService(createRequest(endpoint, 'end'), {
|
@@ -94,7 +104,13 @@ const endTracker = async (endpoint, event_uuid, visitor_uuid) => {
|
|
94
104
|
return responseEnd;
|
95
105
|
};
|
96
106
|
|
97
|
-
const trackEvent = async (
|
107
|
+
const trackEvent = async (
|
108
|
+
endpoint: string,
|
109
|
+
event_uuid: string,
|
110
|
+
visitor_uuid: string,
|
111
|
+
referrer?: string,
|
112
|
+
data?: object
|
113
|
+
) => {
|
98
114
|
const { location, document } = window;
|
99
115
|
referrer = referrer
|
100
116
|
? location.protocol + '//' + location.host + referrer
|
@@ -123,4 +139,10 @@ const trackEvent = async (endpoint, event_uuid, visitor_uuid, referrer, data) =>
|
|
123
139
|
return responseStart;
|
124
140
|
};
|
125
141
|
|
126
|
-
|
142
|
+
const insertParam = (key: string, value: string) => {
|
143
|
+
const url = new URL(window.location.href);
|
144
|
+
url.searchParams.set(key, value);
|
145
|
+
window.history.pushState({ path: url.href }, '', url.href);
|
146
|
+
};
|
147
|
+
|
148
|
+
export { initTracker, startTracker, endTracker, trackEvent, insertParam };
|
@@ -1,13 +1,13 @@
|
|
1
1
|
/* SERVICES */
|
2
|
-
let cache;
|
3
|
-
const assign = (a, b) => {
|
2
|
+
let cache: string;
|
3
|
+
const assign = (a: {}, b: {}) => {
|
4
4
|
Object.keys(b).forEach((key) => {
|
5
5
|
if (b[key] !== undefined) a[key] = b[key];
|
6
6
|
});
|
7
7
|
return a;
|
8
8
|
};
|
9
9
|
|
10
|
-
const trackerService = async (endpoint, payload) => {
|
10
|
+
const trackerService = async (endpoint: string, payload: object) => {
|
11
11
|
const fetchData = await fetch(endpoint, {
|
12
12
|
method: 'POST',
|
13
13
|
body: JSON.stringify(payload),
|