Skip to content

Commit

Permalink
🐳 chore: remove google analytics
Browse files Browse the repository at this point in the history
  • Loading branch information
xytoki committed Jul 8, 2023
1 parent 69d6df3 commit 66dd6d8
Showing 1 changed file with 197 additions and 31 deletions.
228 changes: 197 additions & 31 deletions src/utils/reporting.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { App } from 'vue'
import { Router } from 'vue-router'
import * as Sentry from '@sentry/vue'
Expand All @@ -10,32 +12,205 @@ import { Event, Response, SentryRequest, Session, TransportOptions } from '@sent
import { SentryError, supportsReferrerPolicy, SyncPromise } from '@sentry/utils'
import { BaseTransport } from '@sentry/browser/esm/transports/base'
import { FetchImpl, getNativeFetchImplementation } from '@sentry/browser/esm/transports/utils'
import { apibase } from './apibase'

export function init(app: App, router: Router) {
/// #if SINGLEFILE
checkHm()
.then(() => import('@/plugins/tongji'))
.then((module) => {
module.default()
})
.catch(() => {
// ignore hm failure
})
/// #else
window.dataLayer = window.dataLayer || []
window.gtag = function () {
// eslint-disable-next-line prefer-rest-params
window.dataLayer.push(arguments)
}
window.gtag('js', new Date())
window.gtag('config', 'G-N5RVN34736')
window.gtag('config', 'UA-167575061-1')
export async function init(app: App, router: Router) {
document.head.appendChild(document.createElement('script')).src =
'https://hm.baidu.com/hm.js?9fa0c980766e6a8646c0f814aa40b130'
document.head.appendChild(document.createElement('script')).src =
'https://www.googletagmanager.com/gtag/js?id=G-N5RVN34736'
;((window, website, root) => {
const {
screen: { width, height },
navigator: { language },
location,
document,
history,
} = window
const { hostname, pathname, search } = location
const _data = 'data-'
const endpoint = `${root}/ev`
const screen = `${width}x${height}`
const eventRegex = /data-x-ev-([\w-_]+)/
const eventNameAttribute = _data + 'x-ev'
const delayDuration = 300

/* Helper functions */

const hook = (_this: any, method: any, callback: any) => {
const orig = _this[method]

return (...args: any[]) => {
callback(...args)
return orig.apply(_this, args)
}
}

const getPath = (url: string) => {
if (url.substring(0, 4) === 'http') {
return '/' + url.split('/').splice(3).join('/')
}
return url
}

const getPayload = () => ({
website,
hostname,
screen,
language,
title: document.title,
url: currentUrl,
referrer: currentRef,
})

/* Tracking functions */

const trackingDisabled = () => {
// @ts-expect-error
const { doNotTrack, navigator, external } = window

const msTrackProtection = 'msTrackingProtectionEnabled'
const msTracking = () => {
// @ts-expect-error
return external && msTrackProtection in external && external[msTrackProtection]()
}

// @ts-expect-error
const dnt = doNotTrack || navigator.doNotTrack || navigator.msDoNotTrack || msTracking()

return dnt == '1' || dnt === 'yes'
}

const handlePush = (_state: unknown, title: string, url: string) => {
if (!url) return

currentRef = currentUrl
currentUrl = getPath(url.toString())

if (currentUrl !== currentRef) {
setTimeout(track, delayDuration)
}
}

const handleClick = () => {
const trackElement = (el: HTMLElement): any => {
const attr = el.getAttribute.bind(el)
const eventName = attr(eventNameAttribute)

if (eventName) {
const eventData = {} as Record<string, any>

el.getAttributeNames().forEach((name: string) => {
const match = name.match(eventRegex)

if (match) {
eventData[match[1]] = attr(name)
}
})

return track(eventName, { data: eventData })
}
return Promise.resolve()
}

const callback = (e: any) => {
const findATagParent = (rootElem: HTMLElement | null, maxSearchDepth: number) => {
let currentElement = rootElem
for (let i = 0; i < maxSearchDepth; i++) {
if (currentElement?.tagName === 'A') {
return currentElement
}
currentElement = currentElement?.parentElement || null
if (!currentElement) {
return null
}
}
return null
}

const el = e.target
const anchor = el.tagName === 'A' ? el : findATagParent(el, 10)

if (anchor) {
const { href, target } = anchor
const external =
target === '_blank' || e.ctrlKey || e.shiftKey || e.metaKey || (e.button && e.button === 1)
const eventName = anchor.getAttribute(eventNameAttribute)

if (eventName && href) {
if (!external) {
e.preventDefault()
}
return trackElement(anchor).then(() => {
if (!external) location.href = href
})
}
} else {
trackElement(el)
}
}

document.addEventListener('click', callback, true)
}

const send = (payload: any) => {
if (trackingDisabled()) return
const headers = {
'Content-Type': 'application/json',
} as Record<string, string>
if (typeof cache !== 'undefined') {
headers['x-ev-cache'] = cache
}
return fetch(endpoint, {
method: 'POST',
body: JSON.stringify({ type: 'event', payload }),
headers,
})
.then((res) => res.text())
.then((text) => {
cache = text
})
}

const track = (obj?: any, data?: any) => {
if (typeof obj === 'string') {
return send({
...getPayload(),
name: obj,
data: typeof data === 'object' ? data : undefined,
})
} else if (typeof obj === 'object') {
return send(obj)
} else if (typeof obj === 'function') {
return send(obj(getPayload()))
}
return send(getPayload())
}

// @ts-expect-error
if (!window.$ev) {
// @ts-expect-error
window.$ev = (obj, data) => track(obj, data)
}

let currentUrl = `${pathname}${search}`
let currentRef = document.referrer
let cache: string
let initialized: boolean

if (!trackingDisabled()) {
history.pushState = hook(history, 'pushState', handlePush)
history.replaceState = hook(history, 'replaceState', handlePush)
handleClick()
const init = () => {
if (document.readyState === 'complete' && !initialized) {
track()
initialized = true
}
}
document.addEventListener('readystatechange', init, true)
init()
}
})(window, '8dd6307d-d7ff-4b0a-be63-4e6f9520334e', await apibase('', 'global'))

/// #endif
Sentry.init({
app,
dsn: process.env.VUE_APP_SENTRY,
Expand Down Expand Up @@ -113,15 +288,6 @@ export async function report() {
}
}

/* Check HM */
const checkHm = () =>
new Promise((resolve, reject) => {
const t = new Image()
t.onload = resolve
t.onerror = reject
t.src = 'https://hm.baidu.com/hm.gif'
})

/* Sentry Transport */
export class SimpleFetchTransport extends BaseTransport {
/**
Expand Down

0 comments on commit 66dd6d8

Please sign in to comment.