Skip to content

Commit 526dabe

Browse files
committed
feature: 增加埋点功能
1 parent 52a2630 commit 526dabe

File tree

7 files changed

+525
-0
lines changed

7 files changed

+525
-0
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
import { reportNavigationClick } from "../lib/navigation.js";
2+
import reportSearch from "../lib/search.js";
3+
import { reportSidebarClick } from "../lib/sidebar.js";
4+
import { reportTagsClick } from "../lib/tags.js";
5+
import { reportTopicClick, reportTopicLeave } from "../lib/topic.js";
6+
7+
function isCookieAgreed() {
8+
const regexp = /\bagreed-cookiepolicy=([^;])+/;
9+
const res = document.cookie.match(regexp)?.[1];
10+
return res === "1";
11+
}
12+
13+
export default {
14+
name: "alert",
15+
initialize() {
16+
import(
17+
"https://unpkg.com/@opensig/[email protected]/dist/open-analytics.mjs"
18+
).then(({ OpenAnalytics, getClientInfo, OpenEventKeys }) => {
19+
const oa = new OpenAnalytics({
20+
appKey: "openEuler",
21+
request: (data) => {
22+
if (!isCookieAgreed()) {
23+
disableOA();
24+
return;
25+
}
26+
fetch("https://dsapi.test.osinfra.cn/query/track/openeuler", {
27+
body: JSON.stringify(data),
28+
method: "POST",
29+
headers: { "Content-Type": "application/json" },
30+
});
31+
},
32+
});
33+
34+
/**
35+
* 开启埋点上报功能
36+
*
37+
* 设置上报内容的header信息为浏览器相关信息
38+
*/
39+
const enableOA = () => {
40+
oa.setHeader(getClientInfo());
41+
oa.enableReporting(true);
42+
};
43+
44+
/**
45+
* 关闭埋点上报功能,清除localStorage中关于埋点的条目
46+
*/
47+
const disableOA = () => {
48+
oa.enableReporting(false);
49+
[
50+
"oa-openEuler-client",
51+
"oa-openEuler-events",
52+
"oa-openEuler-session",
53+
].forEach((key) => {
54+
localStorage.removeItem(key);
55+
});
56+
};
57+
58+
function oaReport(event, eventData, $service = "forum", options) {
59+
return oa.report(
60+
event,
61+
async (...opt) => {
62+
return {
63+
$service,
64+
...(typeof eventData === "function"
65+
? await eventData(...opt)
66+
: eventData),
67+
};
68+
},
69+
options
70+
);
71+
}
72+
73+
/**
74+
* 上报PageView事件
75+
* @param $referrer 从哪一个页面跳转过来
76+
*/
77+
const reportPV = ($referrer) => {
78+
oaReport(OpenEventKeys.PV, ($referrer && { $referrer }) || null);
79+
};
80+
81+
/**
82+
* 上报性能指标
83+
*/
84+
const reportPerformance = () => {
85+
oaReport(OpenEventKeys.LCP);
86+
oaReport(OpenEventKeys.INP);
87+
oaReport(OpenEventKeys.PageBasePerformance);
88+
};
89+
90+
function listenCookieSet() {
91+
if (isCookieAgreed()) {
92+
enableOA();
93+
}
94+
const desc = Object.getOwnPropertyDescriptor(
95+
Document.prototype,
96+
"cookie"
97+
);
98+
Object.defineProperty(Document.prototype, "cookie", {
99+
...desc,
100+
set(val) {
101+
desc.set.call(this, val);
102+
if (isCookieAgreed()) {
103+
enableOA();
104+
} else {
105+
disableOA();
106+
}
107+
},
108+
});
109+
}
110+
111+
function listenHistoryChange() {
112+
let referrer;
113+
114+
["replaceState", "pushState"].forEach((method) => {
115+
const native = History.prototype[method];
116+
History.prototype[method] = function (...args) {
117+
try {
118+
if (oa.enabled) {
119+
const beforePath = location.pathname;
120+
native.call(this, ...args);
121+
const afterPath = location.pathname;
122+
if (
123+
beforePath.startsWith("/t/topic/") &&
124+
afterPath.startsWith("/t/topic/") &&
125+
beforePath.split("/")[3] === afterPath.split("/")[3]
126+
) {
127+
return;
128+
}
129+
if (beforePath !== afterPath) {
130+
reportPV(referrer);
131+
window.dispatchEvent(
132+
new CustomEvent("afterRouteChange", {
133+
detail: { from: beforePath, to: afterPath },
134+
})
135+
);
136+
}
137+
} else {
138+
native.call(this, ...args);
139+
}
140+
} catch {
141+
native.call(this, ...args);
142+
} finally {
143+
referrer = location.href;
144+
}
145+
};
146+
});
147+
148+
window.addEventListener("popstate", () => {
149+
try {
150+
const beforePath = new URL(referrer).pathname;
151+
if (beforePath !== location.pathname) {
152+
setTimeout(() => reportPV(referrer));
153+
window.dispatchEvent(
154+
new CustomEvent("afterRouteChange", {
155+
detail: { from: beforePath, to: location.pathname },
156+
})
157+
);
158+
}
159+
} finally {
160+
referrer = location.href;
161+
}
162+
});
163+
}
164+
165+
listenCookieSet();
166+
listenHistoryChange();
167+
reportPV();
168+
reportPerformance();
169+
170+
window._oaReport = oaReport;
171+
window._enableOA = enableOA;
172+
window._disableOA = disableOA;
173+
174+
reportSidebarClick();
175+
reportNavigationClick();
176+
reportTopicClick();
177+
reportTopicLeave();
178+
reportTagsClick();
179+
180+
reportSearch();
181+
});
182+
},
183+
};
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { onNodeInserted } from "./utils.js";
2+
3+
export function reportNavigationClick() {
4+
// 类别下拉点击
5+
onNodeInserted(
6+
".navigation-container .category-drop.is-expanded .select-kit-collection",
7+
(node) => {
8+
window
9+
.$(node)
10+
.children()
11+
.on("click", (ev) =>
12+
window._oaReport("click", {
13+
target: ev.currentTarget.textContent.trim(),
14+
type: "类别",
15+
module: "nav-dropdown",
16+
$url: location.href,
17+
})
18+
);
19+
}
20+
);
21+
// 标签下拉点击
22+
onNodeInserted(
23+
".navigation-container .tag-drop.is-expanded .select-kit-collection",
24+
(node) => {
25+
window
26+
.$(node)
27+
.children()
28+
.on("click", (ev) =>
29+
window._oaReport("click", {
30+
target: ev.currentTarget.textContent.trim(),
31+
type: "标签",
32+
module: "nav-dropdown",
33+
$url: location.href,
34+
})
35+
);
36+
}
37+
);
38+
// 所有下拉点击
39+
onNodeInserted(
40+
".navigation-container .has-selection.is-expanded .select-kit-collection",
41+
(node) => {
42+
window
43+
.$(node)
44+
.children()
45+
.on("click", (ev) =>
46+
window._oaReport("click", {
47+
target: ev.currentTarget.textContent.trim(),
48+
type: "所有",
49+
module: "nav-dropdown",
50+
$url: location.href,
51+
})
52+
);
53+
}
54+
);
55+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import { debounce, onNodeInserted } from "./utils.js";
2+
3+
function onClickSearchInput() {
4+
window._oaReport("click", {
5+
type: "search-input",
6+
module: 'search',
7+
$url: location.href,
8+
});
9+
}
10+
11+
function onInputSearchInput(ev) {
12+
window._oaReport("input", {
13+
type: "search-input",
14+
module: 'search',
15+
content: ev.currentTarget.value.trim(),
16+
$url: location.href,
17+
});
18+
}
19+
20+
function onClickSearchHistory(ev) {
21+
window._oaReport("click", {
22+
type: "search-history",
23+
module: 'search',
24+
target: ev.currentTarget.textContent.trim(),
25+
$url: location.href,
26+
});
27+
}
28+
29+
function onClearSearchHistoryClick() {
30+
window._oaReport("click", {
31+
type: "clear-search-history",
32+
module: 'search',
33+
$url: location.href,
34+
});
35+
}
36+
37+
function onClickSuggestion(ev) {
38+
window._oaReport("click", {
39+
type: "search-suggestion",
40+
module: 'search',
41+
target: ev.currentTarget.textContent.trim(),
42+
detail: ev.currentTarget.href,
43+
$url: location.href,
44+
});
45+
}
46+
47+
function onClickSearchResultTopic(ev) {
48+
const current$ = window.$(ev.currentTarget);
49+
window._oaReport("click", {
50+
type: "search-result",
51+
module: 'search',
52+
target: current$.find(".first-line").text().trim(),
53+
detail: {
54+
path: ev.currentTarget.href,
55+
categories: current$.find(".badge-category__name").text().trim(),
56+
tags: current$.find(".discourse-tags").text().trim(),
57+
},
58+
$url: location.href,
59+
});
60+
}
61+
62+
export default function reportSearch() {
63+
onNodeInserted(
64+
".search-input-wrapper input",
65+
(node) => {
66+
window.$(node).on("click", onClickSearchInput);
67+
window.$(node).on("input", debounce(onInputSearchInput, 300));
68+
window.$(node).on("keydown", (ev) => {
69+
if (ev.key === "Enter") {
70+
window._oaReport("input", {
71+
type: "search",
72+
module: 'search',
73+
content: ev.currentTarget.value.trim(),
74+
$url: location.href,
75+
});
76+
}
77+
});
78+
}
79+
);
80+
81+
// 历史记录点击
82+
onNodeInserted(
83+
".search-menu-panel .search-menu-recent",
84+
(node) => {
85+
window
86+
.$(node)
87+
.children(".search-menu-assistant-item")
88+
.on("click", onClickSearchHistory);
89+
// 清除历史记录
90+
window
91+
.$(node)
92+
.find(".clear-recent-searches")
93+
.on("click", onClearSearchHistoryClick);
94+
}
95+
);
96+
97+
// 联想/帖子结果点击
98+
onNodeInserted(
99+
".search-menu-panel .results div[class^=search-result]",
100+
(node) => {
101+
if (node.classList.contains("search-result-topic")) {
102+
// 话题结果点击
103+
window.$(node).find(".list .item a").on("click", onClickSearchResultTopic);
104+
} else {
105+
// 联想结果点击
106+
window.$(node).find(".list .item a").on("click", onClickSuggestion);
107+
}
108+
}
109+
);
110+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { onNodeInserted } from "./utils.js";
2+
3+
export function reportSidebarClick() {
4+
onNodeInserted("#sidebar-section-content-categories", (node) => {
5+
window
6+
.$(node)
7+
.children()
8+
.on("click", (ev) => {
9+
window._oaReport("click", {
10+
target: ev.currentTarget.textContent.trim(),
11+
level1: "类别",
12+
module: "sidebar",
13+
$url: location.href,
14+
});
15+
});
16+
});
17+
onNodeInserted("#sidebar-section-content-tags", (node) => {
18+
window
19+
.$(node)
20+
.children()
21+
.on("click", (ev) => {
22+
window._oaReport("click", {
23+
target: ev.currentTarget.textContent.trim(),
24+
level1: "标签",
25+
module: "sidebar",
26+
$url: location.href,
27+
});
28+
});
29+
});
30+
}

0 commit comments

Comments
 (0)