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.
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),