Compile "Google Extension", convenient and "self-test", whether the reported information is correct or not
Recommend the introduction to Google extension & svelte article I wrote before:
Remember a simple and easy-to-understand practical sharing session of the front-end "chrome extension" (
Remember a front-end "chrome plug-in" basic actual combat sharing meeting (recommended collection) (Part 2)
Talk about Svelte.js technology, what it does and how to achieve it (on)
Talk about Svelte.js technology, what it does and how to achieve it (Part 2)
background
After developing the project’s buried point function, I need to perform a buried point self-test. At this time, I can only Network
on the console. Since the request parameter of the buried point is an "object type", I need to pass the parameters one by one. Click to open and find the key params
params
is a string serialized by json, you need to perform JSON.parse(xxxxx.params);
, and then open the array structure in it. Because multiple buried point information may be reported together,
JSON.parse
is a data, and finally Also filter out the ten inherent parameters inside and only look at our newly added buried point parameters.
The above process is very regular, so it can be abstracted into a tool search logic, then we can disassemble the problem into 3 steps:
- (Display) There is a suitable interface to conveniently display the request data you want.
- (Get) Intercept the request you want.
- (Processing) Analyze the requested parameters according to fixed rules, and remove the parameters and parents that do not need to be viewed.
- (Configuration) It is possible to configure which requests need to be monitored.
Of course, it is not just the embedding this function, as long as you have the need to analyze api data, you can do similar plug-ins.
final effect
1. The definition of simulation data
Buried point report data I will show a general data structure here. You can adjust it according to your business. Assuming that the following data structure is the report parameter of the buried point report api
[
{
events: [
{
eventName: "事件名: 点击事件",
params:
'{"default1":"xxxxx","default2":"xxxxx","default3":"xxxxx","default4":"xxxxx","default5":"xxxxx","default6":"xxxxx","startTime":"xxxxx","endTime":"xxxxxxx", "new1":"nnnnnn1", "new2":"nnnnnn2"}',
xxxxxxxx: 1636179764881,
xxxxxxx: 0,
},
{
eventName: "事件名: 取消事件",
params:
'{"default1":"xxxxx","default2":"xxxxx","default3":"xxxxx","default4":"xxxxx","default5":"xxxxx","default6":"xxxxx","startTime":"xxxxx","endTime":"xxxxxxx", "new1":"nnnnnn2", "new3":"nnnnnn3"}',
xxxxxxxx: 1636179764881,
xxxxxxx: 0,
},
],
user: {
userId: 123,
userName: "lulu",
},
header: {
app_id: 999,
os_name: "mac",
os_version: "10_15_7",
device_model: "Macintosh",
language: "zh-CN",
},
},
];
- The passing parameter itself is an "object type"
- The first layer is mainly "embedded events", "user information", "device information & more"
- "events" is an array of events
- "eventName" event name, "params" contains event parameters that are "JSON serialized"
- There are some default values in "params" that we don't need to look at, because each buried point will bring some default information like "path information" & "stay event" & "user operation path", etc. These information do not need to be manually added by us. There is no need to look at his correctness every time.
- "new1, new2, new3" are the newly added parameters, which are the parameters we will verify this time
2. Simulate the sending of buried point data
Write two buttons responsible for reporting the buried request, which is convenient for our subsequent verification, and create a new html file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<button onclick="send(`https://zhangzhaosong1.com/`)">点击上报1</button>
<button onclick="send(`https://zhangzhaosong2.com/`)">点击上报2</button>
<script>
function send(url) {
fetch(url, {
method: "post",
headers: {
"Content-Type": "application/json;charset=utf-8;",
},
body: JSON.stringify([
{
events: [
{
eventName: "事件名: 点击事件",
params:
'{"default1":"xxxxx","default2":"xxxxx","default3":"xxxxx","default4":"xxxxx","default5":"xxxxx","default6":"xxxxx","startTime":"xxxxx","endTime":"xxxxxxx", "new1":"nnnnnn1", "new2":"nnnnnn2"}',
xxxxxxxx: 1636179764881,
xxxxxxx: 0,
},
{
eventName: "事件名: 取消事件",
params:
'{"default1":"xxxxx","default2":"xxxxx","default3":"xxxxx","default4":"xxxxx","default5":"xxxxx","default6":"xxxxx","startTime":"xxxxx","endTime":"xxxxxxx", "new1":"nnnnnn2", "new3":"nnnnnn3"}',
xxxxxxxx: 1636179764881,
xxxxxxx: 0,
},
],
user: {
userId: 123,
userName: "lulu",
},
header: {
app_id: 999,
os_name: "mac",
os_version: "10_15_7",
device_model: "Macintosh",
language: "zh-CN",
},
},
]),
}).then(() => {});
}
</script>
</body>
</html>
The main work done in the above html is to add two "buttons", each time you click to send a post request that is a simulated report, each button reports differently, so there are two buttons.
3. Create a Google plug-in project & define icon
Students who have not read the basic courses must read the basic articles first, otherwise they will not be able to change their thinking.
Master file
manifest.json
{
"manifest_version": 2,
"name": "埋:更方便的观察埋点数据",
"description": "更方便的观察埋点数据",
"version": "0.1",
"browser_action": {
"default_icon": "images/logo.png"
}
}
The above icons are free for everyone to play
Introduce plug-ins
Four, define the console tab
Add in the manifest.json file
{
"manifest_version": 2,
"name": "埋:更方便的观察埋点数据",
"description": "更方便的观察埋点数据",
"version": "0.1",
"browser_action": {
"default_icon": "images/logo.png"
},
"devtools_page": "devtools/index.html" // 这句是新增的
}
devtools/index.html
main function of 06187727a841f2 is to introduce js files
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="./index.js"></script>
</body>
</html>
devtools/index.js
main function is to create a tab
chrome.devtools.panels.create(
"埋点验证tab, 还原埋点上报信息",
null,
"../panel/index.html",
function () {
console.log("自定义面板创建成功!");
}
);
In panel/index.html
is the content area style of tab:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>创建成功</div>
</body>
</html>
Five, initialize the svelte project
The content in the tab is too lazy to operate dom natively. Using the "react" framework is a bit heavy, so this time I chose the "svelte framework". For specific benefits, you can see the article I wrote before (the article is placed in the head of the article) .
Initial project
npx degit sveltejs/template devpanel
cd ./devpanel
yarn
Let's edit the rollup.config.js
file so that the packaged file is directly placed in the panel
folder.
output: {
sourcemap: false,
format: "iife",
name: "app",
file: production ? "../panel/index.js" : "public/build/bundle.js",
},
And panel
inside index.html
file references point to our index.js documents, as well as the introduction of style
<link rel="stylesheet" href="./bundle.css">
After running the command yarn build
here, the effect is as follows, please click to refresh the plug-in and "F12" to reopen the console:
During development, it is at localhost:5000/
. After development and packaging, it can be launched together with the plug-in.
Six, intercept request
The core function is to intercept requests, let's use onRequestFinished
api
chrome.devtools.network.onRequestFinished.addListener((res) => {})
The data format of the above return value res is as follows:
The key information is there. The request method and URL can be used to compare whether the request needs to be intercepted, and the rest of our work is to parse the "text".
It should be noted that the value of svelte
cannot be read in chrome
, so it needs to be if (chrome) {}
, so I use mock data debugging when developing in svelte.
Seven, processing data
<script>
const path = "https://zhangzhaosong.com/";
import getNowTime from "./getNowTime";
if (chrome) {
let checkEvent = "";
let dataList = [];
const baseKeyArr = [
"default1",
"default2",
"default3",
"default4",
"default5",
"default6",
"startTime",
"endTime",
];
chrome.devtools.network.onRequestFinished.addListener((res) => {
const req = res.request;
if (req.method === "POST" && req.url === path) {
const eventsArr = JSON.parse(req.postData.text);
eventsArr.forEach((item) => {
if (item.events) {
item.events.forEach((event) => {
const params = JSON.parse(event.params);
const res = {};
for (let i in params) {
if (!baseKeyArr.includes(i)) {
res[i] = params[i];
}
}
dataList.unshift({
res,
time: getNowTime(),
eventName: event.eventName,
});
dataList = dataList;
});
}
});
console.log("---", dataList);
}
});
}
</script>
<main>
<div>list</div>
</main>
<style>
</style>
baseKeyArr
This array contains some buried points. The defaultkey
used to filter out the values we don't care about.path
is the request address to be intercepted, of course, it can also be replaced with a regular or the likegetNowTime
Get the current time
Eight, simple design a style
Display the array obtained above in a loop to form a parameter list of intercepted buried events:
<main>
{#each Object.keys(dataList) as item}
<div>
<header>
<span>{dataList[item].time} : </span>
<span class="title">{dataList[item].eventName}</span>
</header>
<ul>
{#each Object.keys(dataList[item].res) as key}
<li>
<span>{key} :</span>
<span>{dataList[item].res[key]}</span>
</li>
{/each}
</ul>
</div>
{/each}
</main>
<style>
.title {
background-color: bisque;
}
</style>
Nine, filter function and clear function
For ease of use, we can add a filter function and a clear function, so that it is more comfortable to view:
end
The website is about to explode. This is the case this time. I hope to make progress with you.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。