Bläddra i källkod

基本加上pageview功能

gemercheung 3 år sedan
förälder
incheckning
e958674086

+ 27 - 3
packages/core/src/basicTrack.ts

@@ -1,22 +1,46 @@
 import { IBaseAction } from '@medici/types';
 import type { SDKInitConfig, PlatformType, SDKConfigType } from './sdk';
 import type { IHistory } from './history';
-
+import { collect } from './collector';
 export class BaseTrack implements IBaseAction {
     protected _platform: PlatformType;
     protected _config: SDKInitConfig;
     protected _history: IHistory;
+    protected _endPoint: string;
+    protected _appId: string;
 
     constructor(params: SDKConfigType) {
         this._config = params.config;
         this._platform = params.platform;
+        this._appId = params.appId;
+        this._endPoint = params.endPoint;
     }
     public trackView(url: string, referrer: string, uuid: string): void {
         console.log('BaseTrack-trackView', url, referrer, uuid);
         console.log('111-playload', this._history.playload);
+        const payload = Object.assign(this._history.playload, {
+            referrer: this._history.currentRef,
+        });
+        collect(this._endPoint, 'pageview', payload);
+    }
+
+    public trackEvent(value: string, type: string, url?: string, uuid?: string): void {
+        console.log('BaseTrack-TrackEvent', value, type, url, uuid);
+        const payload = Object.assign(this._history.playload, {
+            referrer: this._history.currentRef,
+            event_type: 'custom',
+            event_value: value,
+        });
+        collect(this._endPoint, 'event', payload);
     }
 
-    public TrackEvent(value: string, type: string, url: string, uuid: string): void {
-        console.log('BaseTrack-TrackEvent');
+    public sendEvent(value: string, type: string, url?: string, uuid?: string): void {
+        console.log('BaseTrack-sendEvent', value, type, url, uuid);
+        const payload = Object.assign(this._history.playload, {
+            referrer: this._history.currentRef,
+            event_type: type,
+            event_value: value,
+        });
+        collect(this._endPoint, 'event', payload);
     }
 }

+ 3 - 12
packages/core/src/collector.ts

@@ -1,20 +1,11 @@
 import { makeXHRRequest } from './xhr';
 
-export const collect = (type: string, payload: any) => {
-    makeXHRRequest({
-        url: 'xxx',
+export const collect = (url: string, type: string, payload: any): Promise<XMLHttpRequestResponseType> => {
+    return makeXHRRequest({
+        url: url,
         data: {
             type,
             payload,
         },
     });
-    // if (trackingDisabled()) return;
-    // post(
-    //     `${root}/api/collect`,
-    //     {
-    //         type,
-    //         payload,
-    //     },
-    //     res => (cache = res),
-    // );
 };

+ 26 - 20
packages/core/src/event.ts

@@ -1,15 +1,18 @@
-import { getGlobalObject } from '@medici/utils';
 import { Dict } from '@medici/types';
+import { SDK } from './sdk';
+// import { getGlobalObject } from '@medici/utils';
 // export
-const global = getGlobalObject<Window>();
+// const global = getGlobalObject<Window>();
 
 // const eventSelect = "[class*='umami--']";
 export class Eventer {
+    protected _sdk: SDK;
     private _identifier: string;
     private eventSelect: string;
     private eventClassValidate: RegExp;
-    private listeners: Dict<any>;
-    constructor() {
+    private listeners: Dict<any> = {};
+    constructor(_sdk: SDK) {
+        this._sdk = _sdk;
         this._identifier = 'mdc';
         this.eventSelect = `[class*='${this._identifier}--']`;
         this.eventClassValidate = /^mdc--([a-z]+)--([\w]+[\w-]*)$/;
@@ -19,29 +22,32 @@ export class Eventer {
         this.eventClassValidate = new RegExp('^' + identifier + '--([a-z]+)--([w]+[w-]*)$');
     }
 
+    initElementCssEvents(node: HTMLElement): void {
+        const elements = node.querySelectorAll(this.eventSelect);
+        console.log('initElementCssEvents-elements', elements);
+        Array.prototype.forEach.call(elements, this.addCssEvent.bind(this));
+    }
+
     addCssEvent(element: HTMLElement): void {
-        console.log('className', element.getAttribute('class'));
-        console.log('element', element);
         (element.getAttribute('class') || '').split(' ').forEach((className) => {
-            console.log('validate', this.eventClassValidate.test(className));
             if (!this.eventClassValidate.test(className)) return;
-
             const [, type, value] = className.split('--');
+            console.log('addCssEvent', type, value);
             const listener = this.listeners[className]
                 ? this.listeners[className]
                 : (this.listeners[className] = () => {
-                    if (element.tagName === 'A') {
-                        console.log('sendEvent', value, type);
-                        // sendEvent(value, type);
-                    } else {
-                        console.log('trackEvent', value, type);
-                        // trackEvent(value, type);
-                    }
-                });
-
-            console.log('listener', listener)
-
-            // element.addEventListener(type, listener, true);
+                      if (element.tagName === 'A') {
+                          console.log('sendEvent', value, type);
+                          // sendEvent(value, type);
+                          this._sdk.sendEvent(value, type);
+                      } else {
+                          console.log('trackEvent', value, type);
+                          // trackEvent(value, type);
+                          this._sdk.trackEvent(value, type);
+                      }
+                  });
+            // console.log('listener', listener);
+            element.addEventListener(type, listener, true);
         });
     }
 }

+ 35 - 18
packages/core/src/history.ts

@@ -10,12 +10,14 @@ export interface playloadType {
     screen: string;
     language: string;
     url: string;
+    ua: string;
+    referrer?: string;
 }
 export class IHistory {
     protected _sdk: SDK;
     protected _playload: playloadType;
-    private currentRef: string;
-    private currentUrl: string;
+    private _currentRef: string;
+    private _currentUrl: string;
 
     constructor(sdk: SDK, appId?: string) {
         this._sdk = sdk;
@@ -27,6 +29,14 @@ export class IHistory {
         return this._playload;
     }
 
+    get currentUrl(): string {
+        return this._currentUrl;
+    }
+
+    get currentRef(): string {
+        return this._currentRef;
+    }
+    
     init(): void {
         console.log('history init');
         global.document.addEventListener('readystatechange', this.handleReadystatechange.bind(this), true);
@@ -34,7 +44,7 @@ export class IHistory {
         global.history.replaceState = hook(global.history, 'replaceState', this.handlePushState.bind(this));
         const {
             screen: { width, height },
-            navigator: { language },
+            navigator: { language, userAgent },
             location: { hostname, pathname, search },
             // localStorage,
             // document,
@@ -42,14 +52,16 @@ export class IHistory {
         } = global;
 
         const screen = `${width}x${height}`;
-        this.currentUrl = `${pathname}${search}`;
-        this.currentRef = global.document.referrer;
+        this._currentUrl = `${pathname}${search}`;
+        this._currentRef = global.document.referrer;
         this._playload = {
             website: '',
             hostname: hostname,
             screen: screen,
             language: language,
-            url: this.currentUrl,
+            url: this._currentUrl,
+            ua: userAgent,
+            referrer: this._currentRef,
         };
     }
 
@@ -57,23 +69,25 @@ export class IHistory {
         if (global.document.readyState === 'complete') {
             console.log('handleReadystatechange');
             this.observeDocument();
+            this._sdk.eventer.initElementCssEvents(global.document.body);
+            this._sdk.trackView(this._currentUrl, this._currentRef, this._playload.website);
         }
     }
 
     handlePushState(data: any, unused: string, url?: string | URL): void {
         try {
             if (!url) return;
-            this.currentRef = this.currentUrl;
+            this._currentRef = this._currentUrl;
             const newUrl = url.toString();
             if (newUrl.substring(0, 4) === 'http') {
-                this.currentUrl = '/' + newUrl.split('/').splice(3).join('/');
+                this._currentUrl = '/' + newUrl.split('/').splice(3).join('/');
             } else {
-                this.currentUrl = newUrl;
+                this._currentUrl = newUrl;
             }
-            console.log('diff', this.currentUrl !== this.currentRef);
-            if (this.currentUrl !== this.currentRef) {
+            console.log('diff', this._currentUrl !== this._currentRef);
+            if (this._currentUrl !== this._currentRef) {
                 console.log('trackView', data, unused, url);
-                this._sdk.trackView(this.currentUrl, this.currentRef, this._playload.website);
+                this._sdk.trackView(this._currentUrl, this._currentRef, this._playload.website);
                 //   trackView();
             }
         } catch (error) {
@@ -86,13 +100,16 @@ export class IHistory {
     observeDocument(): void {
         const monitorMutate = (mutations: MutationRecord[]) => {
             console.log('mutations', mutations);
+            const nodeGroup: Node[][] = [];
             mutations.forEach((mutation: MutationRecord) => {
-                const element: Node = mutation.target;
-                console.log('element-1-dataset', (element as HTMLElement).dataset);
-                console.log('element-2', (element as HTMLElement).getAttribute('class'));
-                // this._sdk.eventer.addCssEvent(element as HTMLElement);
-                //   addEvent(element);
-                //   addEvents(element);
+                // const element: Node = mutation.target;
+                nodeGroup.push(Array.from(mutation.addedNodes));
+            });
+            Array.from(nodeGroup.flat()).forEach((item: Node) => {
+                // console.log('element-nodeGroup', item);
+                if ('getAttribute' in (item as HTMLElement)) {
+                    this._sdk.eventer.addCssEvent(item as HTMLElement);
+                }
             });
         };
 

+ 3 - 2
packages/core/src/sdk.ts

@@ -21,8 +21,9 @@ export interface SDKConfigType {
 export class SDK extends BaseTrack {
     protected _platform: PlatformType;
     protected _config: SDKInitConfig;
-    public eventer = new Eventer();
-    // private _history: IHistory;
+
+    public eventer = new Eventer(this);
+    public _history: IHistory;
 
     constructor(params: SDKConfigType) {
         super(params);

+ 4 - 3
packages/core/src/xhr.ts

@@ -3,16 +3,17 @@ export interface BrowserTransportOptions {
     data: any;
 }
 
-export const makeXHRRequest = (options: BrowserTransportOptions): PromiseLike<XMLHttpRequestResponseType> => {
+export const makeXHRRequest = (options: BrowserTransportOptions): Promise<XMLHttpRequestResponseType> => {
     return new Promise((resolve, reject) => {
         const xhr = new XMLHttpRequest();
+        xhr.open('POST', options.url, true);
+        xhr.setRequestHeader('Content-Type', 'application/json');
         xhr.onerror = reject;
         xhr.onreadystatechange = (): void => {
             if (xhr.readyState === 4) {
                 resolve(xhr.response);
             }
         };
-        xhr.open('POST', options.url);
-        xhr.send(options.data);
+        xhr.send(JSON.stringify(options.data));
     });
 };

+ 2 - 1
packages/types/src/event.ts

@@ -13,7 +13,8 @@ export interface TrackActionOption extends Dict<any> {
 }
 export interface IBaseAction {
     trackView(url: string, referrer: string, uuid: string): void;
-    TrackEvent(value: string, type: string, url: string, uuid: string): void;
+    trackEvent(value: string, type: string, url?: string, uuid?: string): void;
+    sendEvent(value: string, type: string, url?: string, uuid?: string): void;
 }
 
 export interface ICustomAction {

+ 10 - 7
play/src/components/home.vue

@@ -1,15 +1,18 @@
-<script setup lang="ts">
-</script>
+<script setup lang="ts"></script>
 
 <template>
-  <h1>home</h1>
-  <router-link to="page1">page1</router-link>
-  <router-link to="page2">page2</router-link>
-
+    <h1>home</h1>
+    <router-link to="page1">page1</router-link>
+    <router-link to="page2">page2</router-link>
+    <router-link to="page3" class="mdc--click-register">page3</router-link>
+    <div>
+        <button class="mdc--click--login">action-to-login</button>
+        <button class="mdc--click--pay">action-to-pay</button>
+    </div>
 </template>
 
 <style scoped>
 .read-the-docs {
-  color: #888;
+    color: #888;
 }
 </style>

+ 2 - 2
play/src/components/page1.vue

@@ -2,8 +2,8 @@
 
 <template>
     <h1>page1</h1>
-    <button class="mdc--track-1">test 1 button action tracker</button>
-    <button class="mdc--track-2">test 2 button action tracker</button>
+    <button class="mdc--click--signin-btn test test1">test 1 button action tracker</button>
+    <button class="mdc--click--signout-btn test test1">test 2 button action tracker</button>
 </template>
 
 <style scoped>

+ 14 - 0
play/src/components/page3.vue

@@ -0,0 +1,14 @@
+<script setup lang="ts">
+
+</script>
+
+<template>
+  <h1>page2</h1>
+
+</template>
+
+<style scoped>
+.read-the-docs {
+  color: #888;
+}
+</style>

+ 5 - 0
play/src/router.ts

@@ -23,5 +23,10 @@ export const router = createRouter({
             component: Page2,
             // props: (to) => ({ waited: to.meta.waitedFor }),
         },
+        {
+            path: '/page3',
+            component: Page2,
+            // props: (to) => ({ waited: to.meta.waitedFor }),
+        },
     ],
 });

+ 2 - 2
tsconfig.build.json

@@ -1,9 +1,9 @@
 {
     "compilerOptions": {
-        "target": "es2016",
+        "target": "ES2016",
         "module": "esnext",
         "moduleResolution": "node",
-        "lib": ["es2015", "es5", "es6", "dom"],
+        "lib": ["ESNext", "es2015", "es5", "es6", "dom"],
         "esModuleInterop": true,
         "sourceMap": true,
         "declaration": true,