关于前端:编写谷歌扩展便捷自测埋点上报信息是否正确

编写”谷歌扩大”便捷”自测”埋点上报信息是否正确

举荐我之前写的谷歌扩大入门&svelte入门文章:

记一次前端”chrome扩大”简略易懂的实战分享会(上)
记一次前端”chrome插件”根底实战分享会(倡议珍藏)(下篇)
聊聊Svelte.js技术它做了什么以及如何实现的(上)
聊聊Svelte.js技术它做了什么以及如何实现的(下)

背景

     每次开发完我的项目的埋点性能后都须要进行埋点自测, 此时我只能通过在控制台的Network上进行筛选, 因为埋点的申请参数是个”对象类型”, 须要将传参逐一点开并且找到params这个key, 然而params是一个被json序列化的字符串, 须要进行JSON.parse(xxxxx.params);, 而后再关上它外面的数组构造因为可能是多个埋点信息一起上报所以JSON.parse后是个数据, 最初还要将外面的十个固有参数过滤掉只看咱们新增的埋点参数。

     上述过程很有法则所以能够形象成一个工具查找的逻辑, 那咱们能够把问题拆解成3步:

  1. (展现)有适合的界面不便显示你想要的申请数据。
  2. (获取)拦挡到你想要的申请。
  3. (解决)将申请的参数按固定规定解析, 剔除不须要查看的参数与父级。
  4. (配置)可配置哪些申请须要被监测。

     当然不只是埋点这个性能, 只有你有剖析api数据的需要都能够做相似的插件。

最终成果

一、模仿数据的定义

     埋点上报数据我这里展现一个大略的数据结构, 大家依据业务自行调节, 假如上面的数据结构就是埋点上报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",
    },
  },
];
  1. 传参自身是个”对象类型”
  2. 第一层次要是”埋点事件”, “用户信息”, “设施信息&更多”
  3. “events”是事件数组
  4. “eventName”事件名称, “params”外面是被”JSON序列化”的事件参数
  5. “params”里有一些咱们不必看的默认值, 因为每个埋点都会带一些像”门路信息”&”停留事件”&”用户操作门路”等等的默认信息, 这些信息不必咱们手动退出所以也就不必每次都看他的正确性。
  6. “new1, new2, new3″是咱们新退出的参数, 也就是咱们这次重点验证的参数

二、模仿埋点数据的收回

     编写两个按钮负责上报埋点申请, 不便咱们后续的验证, 新建一个html文件:

<!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>

     下面html外面次要做的工作是增加两个”按钮”, 每次点击收回埋点的模仿上报的post申请, 每个按钮上报的不一样所以有两个按钮。

三、创立一个谷歌插件我的项目 & 定义图标

     没看过基础课的同学肯定要先看看根底文章, 否则没法转换思维。

主文件

manifest.json

{
  "manifest_version": 2,
  "name": "埋:更不便的察看埋点数据",
  "description": "更不便的察看埋点数据",
  "version": "0.1",
  "browser_action": {
    "default_icon": "images/logo.png"
  }
}

上述的图标大家自由发挥哈

引入插件

四、定义控制台tab

     在manifest.json文件外面减少

{
  "manifest_version": 2,
  "name": "埋:更不便的察看埋点数据",
  "description": "更不便的察看埋点数据",
  "version": "0.1",
  "browser_action": {
    "default_icon": "images/logo.png"
  },
  "devtools_page": "devtools/index.html" // 这句是新增的
}

devtools/index.html次要性能只是引入js文件

<!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次要性能是创立tab

chrome.devtools.panels.create(
  "埋点验证tab, 还原埋点上报信息",
  null,
  "../panel/index.html",
  function () {
    console.log("自定义面板创立胜利!");
  }
);

panel/index.html外面才是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>

五、初始化svelte我的项目

     tab外面的内容咱们懒得原生操作dom, 应用”react”框架有点重, 所以这次我抉择了”svelte框架”, 具体它的益处能够看看我之前写的文章(文章放在文章头部了)。

初始我的项目
npx degit sveltejs/template devpanel

cd ./devpanel

yarn

咱们编辑一下 rollup.config.js文件, 使得打包后的文件间接放入panel文件夹里。

  output: {
    sourcemap: false,
    format: "iife",
    name: "app",
    file: production ? "../panel/index.js" : "public/build/bundle.js",
  },

并且将panel外面的index.html文件的文件援用指向咱们的index.js文件, 以及引入款式 <link rel="stylesheet" href="./bundle.css">

在这里运行命令yarn build后的成果如下, 请点击刷新插件并且”F12″从新关上控制台:

开发时候在localhost:5000/, 开发完打包就能够和插件一起上线了。

六、拦挡申请

     外围性能就是拦挡申请, 让咱们应用onRequestFinishedapi

chrome.devtools.network.onRequestFinished.addListener((res) => {})

     下面的返回值res的数据格式如下图:

     要害信息都有, 申请办法与url能够用来比对是否为须要拦挡的申请, 而咱们剩下的工作就是对”text”的解析了。

     要留神的是, svelte外面无奈读取到chrome的值, 所以须要用if (chrome) {}包裹起来, 所以在svelte外面开发时我应用的是mock数据调试。

七、解决数据

<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>

  1. baseKeyArr这个数组外面是一些埋点默认的key, 用来过滤掉咱们不关怀的值
  2. path是要拦挡的申请地址, 当然也能够换成正则之类的
  3. getNowTime获取以后的工夫

八、简略设计个款式

     将下面失去的数组循环显示进去, 造成一个被拦挡的埋点事件的参数list:

<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>

九、过滤性能与革除性能

     为了好用咱们能够增加一个过滤性能与革除性能, 这样查看起来更难受:

end

     网站快卡炸了, 这次就是这样, 心愿与你一起提高。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理