aesirx-analytics 1.0.6 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. package/README.md +18 -9
  2. package/dist/index.js +5 -0
  3. package/package.json +12 -34
  4. package/src/AnalyticsNext/{handle.js → handle.tsx} +42 -10
  5. package/src/AnalyticsNext/index.tsx +26 -0
  6. package/src/AnalyticsReact/handle.tsx +72 -0
  7. package/src/AnalyticsReact/index.tsx +21 -0
  8. package/src/{analytics.js → analytics.ts} +15 -20
  9. package/src/{index.js → index.ts} +1 -1
  10. package/src/utils/AnalyticsContextProvider.tsx +57 -0
  11. package/src/utils/{index.js → index.ts} +32 -10
  12. package/src/utils/{services.js → services.ts} +3 -3
  13. package/build/analytics.js +0 -1
  14. package/build/lib/bundles/bundle.esm.min.js +0 -2
  15. package/build/lib/bundles/bundle.esm.min.js.map +0 -1
  16. package/build/lib/cjs/AnalyticsNext/handle.js +0 -119
  17. package/build/lib/cjs/AnalyticsNext/handle.js.map +0 -1
  18. package/build/lib/cjs/AnalyticsNext/index.js +0 -51
  19. package/build/lib/cjs/AnalyticsNext/index.js.map +0 -1
  20. package/build/lib/cjs/AnalyticsReact/handle.js +0 -77
  21. package/build/lib/cjs/AnalyticsReact/handle.js.map +0 -1
  22. package/build/lib/cjs/AnalyticsReact/index.js +0 -51
  23. package/build/lib/cjs/AnalyticsReact/index.js.map +0 -1
  24. package/build/lib/cjs/analytics.js +0 -197
  25. package/build/lib/cjs/analytics.js.map +0 -1
  26. package/build/lib/cjs/index.js +0 -35
  27. package/build/lib/cjs/index.js.map +0 -1
  28. package/build/lib/cjs/utils/AnalyticsContextProvider.js +0 -39
  29. package/build/lib/cjs/utils/AnalyticsContextProvider.js.map +0 -1
  30. package/build/lib/cjs/utils/index.js +0 -202
  31. package/build/lib/cjs/utils/index.js.map +0 -1
  32. package/build/lib/cjs/utils/services.js +0 -51
  33. package/build/lib/cjs/utils/services.js.map +0 -1
  34. package/build/lib/esm/AnalyticsNext/handle.js +0 -124
  35. package/build/lib/esm/AnalyticsNext/handle.js.map +0 -1
  36. package/build/lib/esm/AnalyticsNext/index.js +0 -56
  37. package/build/lib/esm/AnalyticsNext/index.js.map +0 -1
  38. package/build/lib/esm/AnalyticsReact/handle.js +0 -82
  39. package/build/lib/esm/AnalyticsReact/handle.js.map +0 -1
  40. package/build/lib/esm/AnalyticsReact/index.js +0 -56
  41. package/build/lib/esm/AnalyticsReact/index.js.map +0 -1
  42. package/build/lib/esm/analytics.js +0 -198
  43. package/build/lib/esm/analytics.js.map +0 -1
  44. package/build/lib/esm/index.js +0 -35
  45. package/build/lib/esm/index.js.map +0 -1
  46. package/build/lib/esm/utils/AnalyticsContextProvider.js +0 -45
  47. package/build/lib/esm/utils/AnalyticsContextProvider.js.map +0 -1
  48. package/build/lib/esm/utils/index.js +0 -206
  49. package/build/lib/esm/utils/index.js.map +0 -1
  50. package/build/lib/esm/utils/services.js +0 -54
  51. package/build/lib/esm/utils/services.js.map +0 -1
  52. package/build/lib/types/AnalyticsNext/handle.d.ts +0 -3
  53. package/build/lib/types/AnalyticsNext/handle.d.ts.map +0 -1
  54. package/build/lib/types/AnalyticsNext/index.d.ts +0 -3
  55. package/build/lib/types/AnalyticsNext/index.d.ts.map +0 -1
  56. package/build/lib/types/AnalyticsReact/handle.d.ts +0 -3
  57. package/build/lib/types/AnalyticsReact/handle.d.ts.map +0 -1
  58. package/build/lib/types/AnalyticsReact/index.d.ts +0 -3
  59. package/build/lib/types/AnalyticsReact/index.d.ts.map +0 -1
  60. package/build/lib/types/index.d.ts +0 -5
  61. package/build/lib/types/index.d.ts.map +0 -1
  62. package/build/lib/types/index.min.js +0 -1
  63. package/build/lib/types/utils/AnalyticsContextProvider.d.ts +0 -3
  64. package/build/lib/types/utils/AnalyticsContextProvider.d.ts.map +0 -1
  65. package/build/lib/types/utils/index.d.ts +0 -5
  66. package/build/lib/types/utils/index.d.ts.map +0 -1
  67. package/build/lib/types/utils/services.d.ts +0 -2
  68. package/build/lib/types/utils/services.d.ts.map +0 -1
  69. package/src/AnalyticsNext/index.js +0 -30
  70. package/src/AnalyticsReact/handle.js +0 -39
  71. package/src/AnalyticsReact/index.js +0 -29
  72. 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
- return <AnalyticsReact pathname={location.pathname}>{children}</AnalyticsReact>;
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
- ###### `<AnalyticsContainer>` need to using inside `<Router>` component
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.6",
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": "build/lib/cjs/index.js",
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
- "cross-env": "^7.0.3",
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:esm": "cross-env BABEL_ENV=esmUnbundled babel src --extensions '.js' --out-dir 'build/lib/esm' --source-maps",
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
- "@babel/cli": "^7.21.0",
60
- "@babel/core": "^7.19.6",
61
- "@babel/eslint-parser": "^7.18",
62
- "@babel/plugin-transform-runtime": "^7.19.6",
63
- "@babel/preset-env": "^7.20.2",
64
- "@babel/preset-react": "^7.18.6",
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
- "rollup": "^2.79.1",
75
- "rollup-plugin-terser": "^7.0.2",
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
- const AnalyticsHandle = ({ router, children }) => {
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
- const responseInit = await initTracker(endPoint);
28
- responseInit.event_uuid && AnalyticsStore.setEventID(responseInit.event_uuid);
29
- AnalyticsStore.setUUID(responseInit.visitor_uuid);
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
- if (AnalyticsStore.visitor_uuid_start) {
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.tracker) {
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.tracker = tracker;
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.aesirx1stparty ? window.aesirx1stparty : '';
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
- let attribute = [];
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, null, null, null, {
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
- let anchors = document.getElementsByTagName('a');
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
- let params = new URL(url);
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 (endpoint, url, referrer, user_agent) => {
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.userLanguage || window.navigator.language;
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
- let attributes = [];
24
- for (var key of urlParams.keys()) {
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
- let ip = '';
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 (endpoint, event_uuid, visitor_uuid, referrer) => {
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 (endpoint, event_uuid, visitor_uuid, referrer, data) => {
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
- export { initTracker, startTracker, endTracker, trackEvent };
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),