{"id":23016815,"url":"https://github.com/shadowings-zy/shadow-tracker","last_synced_at":"2025-08-14T07:32:43.427Z","repository":{"id":41292951,"uuid":"247634797","full_name":"shadowings-zy/shadow-tracker","owner":"shadowings-zy","description":"一款轻量级的前端无感知监控框架 / A user experience management framework for monitoring front-end data","archived":false,"fork":false,"pushed_at":"2022-06-26T15:05:26.000Z","size":845,"stargazers_count":33,"open_issues_count":0,"forks_count":7,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-09T15:54:26.751Z","etag":null,"topics":["javascript","typescript"],"latest_commit_sha":null,"homepage":"https://shadowingszy.top/shadow-tracker/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shadowings-zy.png","metadata":{"files":{"readme":"README-EN.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-03-16T07:12:52.000Z","updated_at":"2024-09-17T02:10:50.000Z","dependencies_parsed_at":"2022-07-07T11:22:56.322Z","dependency_job_id":null,"html_url":"https://github.com/shadowings-zy/shadow-tracker","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/shadowings-zy/shadow-tracker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shadowings-zy%2Fshadow-tracker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shadowings-zy%2Fshadow-tracker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shadowings-zy%2Fshadow-tracker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shadowings-zy%2Fshadow-tracker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shadowings-zy","download_url":"https://codeload.github.com/shadowings-zy/shadow-tracker/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shadowings-zy%2Fshadow-tracker/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269794107,"owners_count":24476744,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-10T02:00:08.965Z","response_time":71,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","typescript"],"created_at":"2024-12-15T11:17:47.247Z","updated_at":"2025-08-14T07:32:43.098Z","avatar_url":"https://github.com/shadowings-zy.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# shadow-tracker (English)\n\n## shadow-tracker introduction\n\nshadow-tracker is a sensorless front-end data tracker, which provides the following functions:\n\n| number | function                                                                                                        | log type           |\n| ------ | --------------------------------------------------------------------------------------------------------------- | ------------------ |\n| 1      | Collect the click events, keyboard input events and url change events when the user interacts with the web page | Event Log          |\n| 2      | Collect error information for all JS                                                                            | Error Log          |\n| 3      | Collect all XMLHttpRequest network request information                                                          | XMLHttpRequest Log |\n| 4      | Collect performance data information of page loading                                                            | performance log    |\n| 5      | Collect the user's device information                                                                           | device log         |\n| 6      | provide time travel function, generate nightwatch E2E test code according to user's operation                   | N/A                |\n| 7      | support custom expansion of logs                                                                                | N/A                |\n| 8      | provide log analysis tools                                                                                      | N/A                |\n\nNote: `performance data information of page loading` need browser support `performance API`, and other functions support IE7 and above browsers.\n\n## quick start\n\n### import through NPM\n\n```bash\nnpm install shadow-tracker\n```\n\n```javascript\nimport tracker from 'shadow-tracker';\n\nTracker.Init(); // initialize tracker\nConsole.Log(tracker.Getloglist()); // get log information\n```\n\n### import through the \"script\" tag\n\n```html\n\u003cscript src=\"./shadow-tracker-script.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n  Window.Tracker.Init(); // initialize tracker\n  Console.Log(window.Tracker.Getloglist()); // get the log information\n\u003c/script\u003e\n```\n\nNote: due to the limited server resources, it is recommended to download the shadow-tracker script file from `\"http://www.shadowtracker.top/shadowtracker/script/shadow-tracker-script.js\"`.\n\n## API description\n\n### init(options)\n\nInitialize tracker\n\nParameter Description:\nOptions - configuration item object, see part 4 \"options\"\n\nUse example:\n\n```javascript\ntracker.init({});\n```\n\n### getDeviceInfo()\n\nGet user's device information and write the device information into the loglist. For details, see part 5 \"loglist description and custom log\"\n\nUse example:\n\n```javascript\nconsole.log(tracker.getDeviceInfo());\n```\n\n### getPerformanceInfo()\n\nGet the page performance data and write the page performance information into the loglist. For details, see part 5 \"loglist description and custom log\"\n\nUse example:\n\n```javascript\nconsole.log(tracker.getPerformanceInfo());\n```\n\n### getLogList()\n\nGet all log data. For details, see part 5 \"loglist description and custom log\"\n\nUse example:\n\n```javascript\nconsole.log(tracker.getLogList());\n```\n\n### getTimeTravelCode()\n\nGet the time travel code. For details, see part 6 \"time travel\"\n\nUse example:\n\n```javascript\nconsole.log(tracker.getTimeTravelCode());\n```\n\n### addCustomLog(key, value)\n\nadd custom log，the `logType` of log object is `Custom Log`\n\n使用样例：\n\n```javascript\ntracker.addCustomLog(key, value);\n```\n\n## Options\n\nWhen initialize tracker, a configuration object can be passed in to enrich the functionality of the tracker.\n\n```javascript\n//This is the default configuration item for shadow-tracker, let's take this example\nconst option = {\n  sessionId: `${Date.now()}${Math.floor(Math.random() * 1000)}`, // sessionId, default is current timestamp and random number\n  userId: `${Date.now()}${Math.floor(Math.random() * 1000)}`, // userId, default is current timestamp and random number\n  useClass: false, // whether to use class as the unique ID of the element\n  maxResponseTextLength: 1000, // maximum length of XMLHttpRequest return value\n  timeTracelInitTime: 3000, // wait time for initialization page in generated time travel code\n  timeTravelClickDelayTime: 1000, // delay time of clicking element in generated time travel code\n  timeTracelInputDelayTime: 1000, // delay time of input data in generated time travel code\n  captureEvent: true, // whether to capture event log\n  captureJsError: true, // whether to capture error log\n  captureXMLHttpRequest: true, // whether to capture request log\n  custom: false, // whether to add custom data to the log object\n  customizeLog: function (logType, logContent) {}, // functions that generate custom log data, see part 5 \"LogList description and custom Log\"\n  customizeEventLog: function (event) {}, // functions to generate custom event logs, see part 5 \"LogList description and custom logs\"\n  customizeErrorLog: function (error) {}, // functions to generate custom error logs, see part 5 \"LogList description and custom logs\"\n  customizeXMLHttpRequestLog: function (event) {}, // functions to generate custom XMLHttpRequest logs, see part 5 \"LogList description and custom logs\"\n  customizeDeviceLog: function (userAgent) {}, // functions to generate custom device logs, see part 5 \"LogList description and custom logs\"\n  customizePerformanceLog: function (performance) {} // functions to generate custom performance logs, see part 5 \"LogList description and custom logs\"\n};\n```\n\n## Loglist description and custom log object\n\nLoglist is a JS array for storing all logs. We can use `getloglist()` to get this array, and further develop the logic of log reporting and log storage according to our business needs.\nIn addition, we can expand the log object according to our own business requirements.\n\nIf we need to add custom data, first we need to assign the `custom` attribute in the configuration item object passed in to the tracker to true, and implement the custom data function according to our own needs.\n\n### Log object description\n\n#### Introduction\n\nThe log object is the basic log object, which contains the following properties:\n\n```javascript\n{\n  \"logtime\": 1584262658187, // log generation time\n  \"url\": \"www.shadowingszy.top\", // the URL that generates the log page\n  \"logSession\": \"xxx\", // sessionId\n  \"logUser\": \"xxx\", // userId\n  \"logType\": \"Error Log\", // the types of logs, including: event log | error log | XMLHttpRequest log | device log | performance log | Custom Log\n  \"logContent\": {} // specific log information\n}\n```\n\n#### Custom log object\n\nThe custom log object contains the following properties:\n\n```javascript\n{\n  \"logtime\": 1584262658187, // log generation time\n  \"url\": \"www.shadowingszy.top\", // the URL that generates the log page\n  \"logSession\": \"xxx\", // sessionId\n  \"logUser\": \"xxx\", // userId\n  \"logtype\": \"error log\", // the types of logs, including: event log | error log | XMLHttpRequest log | device log | performance log | Custom Log\n  \"logcontent\": {} // specific log information\n  \"custom\": {// custom log fields\n    \"log\": {}, // the value returned after executing the customizelog() method in the configuration item\n    \"detail\": {} // the value returned by a type of log after executing the corresponding customizeeventlog(), customizeerrorlog(), customizexmlhttprequestlog(), customizedevicelog(), customizeperformancelog() methods in the configuration item\n  }\n}\n```\n\nBy implementing the 'customizelog' method in the configuration item, we can customize the log object and use the return value of the 'customizelog' function as the value of the 'custom. Log' attribute in the log object.\n\n`Customizelog`method parameter description:\n|parameter name | parameter type | parameter description|\n| - | - | - |\n|logType | string | the type of log, including:`Event log | Error log | XMLHttpRequest log | Device log | Performance log | Custom Log`\n|logContent | object | log specific information|\n\n### Event log object\n\n#### Introduction\n\nThe event log object is a log object that records click event, keyboard input event and url change event. It will be displayed in the `logContent` property of the corresponding type of log object.\nEvent log includes two types of log: \"click\" and \"input\", respectively including the following attributes:\n\nClick event:\n\n```javascript\n{\n  \"dompPath\": \"H1\", // the DOM path of the current event\n  \"trackingType\": \"MouseDown\", // event\n  \"offsetX\": \"0.5\", // the relative X coordinate of the current click event. If the current page width is 700, then the X of the click event is 350\n  \"offsetY\": \"0.5\" // the relative X coordinate of the current click event. If the current page width is 700, then the y of the click event is 350\n}\n```\n\nInput event:\n\n```javascript\n{\n  'domPath': 'H1', // the DOM path of the current event\n  \"trackingType\": \"Keyup\", // event\n  \"inputKey\": \"3\", // the input value\n  \"currentValue\": \"123\" // the value of the current input box\n}\n```\n\nUrl change event：\n\n```javascript\n{\n  \"newUrl\": \"https://www.shadowingszy.top/#new\"\n  \"oldUrl\": \"https://www.shadowingszy.top/#old\"\n  \"trackingType\": \"urlchange\"\n}\n```\n\n#### Custom description\n\nBy implementing the `customizeEventLog()` method in the configuration item, we can customize the log object and use the return value of the `customizeEventLog()` function as the value of the `custom.detail` attribute in the log object.\n\n`customizeEventLog()` method parameter description:\n|parameter name | parameter type | parameter description\n| - | - | - |\n|event | object | the event object that currently triggers the event\n\n### Error log object\n\n#### Introduction\n\nError log object is a log object that records JS errors on the current page. It will be displayed in the `logContent` property of the corresponding type of log object.\nThe error log object contains the following properties:\n\n```javascript\n{\n  \"errorType\": \"Customize\", // the type of error, including: JS | customize | window.onerror | window.onunhandledrection\n  \"errorMsg\": \"this is error message\", // error message\n}\n```\n\nNote: errorType details\n|type | Description |\n| - | - |\n|js | JavaScript code error|\n|customize | `console. Error()` reports an error, which does not contain error stack information|\n|window.onerror | `window.onerror` callback error|\n|window.onunhandledrejection | `window.onunhandledrejection` callback reports an error|\n\n#### customize description\n\nBy implementing the `customizeErrorLog()` method in the configuration item, we can customize the log object and use the return value of the `customizeErrorLog()` function as the value of the `custom.detail` attribute in the log object.\n\n`customizeErrorLog` method parameter description:\n|parameter name | parameter type | parameter description\n| - | - | - |\n|error | object | the error object that triggered the error\n\n### XMLHttpRequest log object\n\n#### Introduction\n\nXMLHttpRequest log object is a log object that records XMLHttpRequest. It will be displayed in the `logContent` attribute of the corresponding type of log object.\nIt can also capture log of `fetch API`\n\nLog content:\n\n```javascript\n{\n  \"duration\": 10, // request duration\n  \"event\": \"ajaxLoadEnd\", // current event\n  \"status\": 200, // status code\n  \"response\": \"\", // return content\n  \"url\": \"xxx\" // request url\n}\n```\n\n#### customize description\n\nThis kind of log not support customize.\n\n### Device log object\n\n#### Introduction\n\nThe device log object is a log object that records user device information. It will be displayed in the `logContent` property of the corresponding type of log object, including the following properties:\n\n```javascript\n{\n  \"browser\": true, // whether it is a PC browser\n  \"mobile\": false, // is the mobile browser\n  \"type\": \"computer\", // the category of the current terminal, including: computer, IOS, Android, wechat, Windows Phone, unknown\n  \"version\": \"80.0.3987.132\", // version number\n  \"name\": \"Chrome\", // the category of the current browser, including: MSIE, Firefox, chrome, sarfari, Android, IOS, unknown\n  \"userAgent\": \"\", // value of navigator.useragent\n  \"screenWidth\": 1920, // screen width\n  \"screenHeight\": 1080, // screen height\n  \"clientWidth\": 1920, // client width\n  \"clientHeight\": 1080, // client height\n}\n```\n\n#### customize description\n\nBy implementing the `customizeDeviceLog()` method in the configuration item, we can customize the log object and take the return value of the `customizeDeviceLog()` function as the value of the `custom.detail` attribute in the log object.\n\n`customizeDeviceLog()` method parameter description:\n|parameter name | parameter type | parameter description\n| - | - | - |\n|device | object | `navigator.useragent` object\n\n### performance log object\n\n#### Basic instructions\n\nThe performance log object is a log object that records page performance data. It will be displayed in the `logContent` property of the corresponding type of log object, including the following properties:\n\n```javascript\n{\n  \"loadType\": \"reload\",\n  \"loadPageTime\": 0, // the time when the page loading is completed\n  \"domReadyTime\": 0, // time to parse DOM tree structure\n  \"redirectTime\": 0, // redirection time\n  \"domainLookupTime\": 0, // DNS query time\n  \"timeToFirstByte\": 0, // the time taken to read the first byte of the page, that is, the time taken by the user to get your resources\n  \"requestTime\": 0, // time when content loading is completed\n  \"loadEventTime\": 0, // the time when the onload callback function is executed\n  \"cacheTime\": 0, // DNS cache time\n  \"unloadTime\": 0, // time to unload the page\n  \"connectTime\": 0 // the time for TCP to establish the connection and complete the handshake\n}\n```\n\nNote: the performance log object uses `window.performance` to record page performance data, so only IE9 and above browsers are supported\n\n#### User defined description\n\nBy implementing the `customizePerformanceLog()` method in the configuration item, we can customize the log object and take the return value of the `customizePerformanceLog()` function as the value of the `custom.detail` attribute in the log object.\n\n`customizePerformanceLog()` method parameter description:\n|parameter name | parameter type | parameter description\n| - | - | - |\n|performance | object | `window.performance` object\n\n## Time Travel feature\n\nThis feature reproduces all user actions based on Event Log data in the logList and generates NightWatch E2E test code from the logs. We only need to install NightWatch and execute this code to reproduce user actions.\n\nWe can set parameters in the tacker configuration item.\n|Parameter Name|Parameter Description\n| - | - |\n| timeTracelInitTime | Initialize page wait time in generated time travel code|\n| timeTravelClickDelayTime | Delay time of click on the element in generated time travel code |\n| timeTracelInputDelayTime | Delay time of input data in generated time travel code|\n\nGenerate code examples:\n\n```javascript\nfunction test(browser) {\n  browser\n    .url('www.shadowingszy.top')\n    .pause(3000)\n    .assert.elementPresent('#xml-test')\n    .click('#xml-test')\n    .pause(2000)\n    .assert.elementPresent('#get-log')\n    .click('#get-log')\n    .pause(2000)\n    .assert.elementPresent('#get-log')\n    .click('#get-log')\n    .pause(1000);\n}\n```\n\n## shadow-tracker-analyzer introduction\n\n### import through NPM\n\n```bash\nnpm install shadow-tracker-analyzer\n```\n\n```javascript\nimport { ShadowTrackerAnalyzer } from 'shadow-tracker-analyzer';\n\nconst logList = []; // log list upload by shadow-tracker\n\nconst analyzer = new ShadowTrackerAnalyzer({\n  maxLogListLength: 50000,\n  jumpOutTimeLimit: 30 * 1000\n});\n\nanalyzer.addLog(logList); // add log to analyzer\n\nconst overview = analyzer.getOverview(); // get data overview\nconst urlStatisticInfo = analyzer.getUrlStatisticInfo(); // get url statistic information\nconst deviceInfo = analyzer.getDeviceInfo(); // get device information\nconst performanceInfo = analyzer.getPerformanceInfo(); // get performance information\n```\n\n### Options\n\nWhen initialize analyzer, a configuration object can be passed in to enrich the functionality of the analyzer.\n\n```javascript\nconst option = {\n  maxLogListLength: 50000, // max log list count\n  jumpOutTimeLimit: 30 * 1000 // jump out time limit, for jump out rate\n};\n```\n\n### API\n\n#### getOverview()\n\nget data overview\n\nreturn value:\n\n```javascript\n{\n  pv: 85, // pv\n  uv: 10, // uv\n  jumpOutRate: 0.27058823529411763, // jump out rate\n  averageVisitTime: 6885017 // averate visit time\n}\n```\n\n#### getUrlStatisticInfo()\n\nget url statistic\n\nreturn value：\n\n```javascript\n[\n  {\n    url: 'https://a.com/b', // visit url\n    visitNumber: 61 // visit number\n  },\n  {\n    url: 'https://a.com/c',\n    visitNumber: 54\n  }\n];\n```\n\n#### getDeviceInfo()\n\nget device information\n\nreturn value：\n\n```javascript\n{\n  screenInfo: [ // screen information\n    { info: '1280x800', number: 10 },\n    { info: '1920x1080', number: 35 }\n  ],\n  clientInfo: [ // client(window) information\n    { info: '980x1708', number: 1 },\n    { info: '1024x640', number: 1 }\n  ],\n  browserInfo: [ // browser information\n    { info: 'iphone(ios)', number: 1 },\n    { info: 'firefox(computer)', number: 4 },\n    { info: 'chrome(computer)', number: 86 }\n  ]\n}\n```\n\n#### getPerformanceInfo()\n\nget performance information\n\nreturn value：\n\n```javascript\n{\n  cacheTime: 8090, // DNS cache time\n  connectTime: 18431, // the time for TCP to establish the connection and complete the handshake\n  domReadyTime: 59322, // time to parse DOM tree structure\n  domainLookupTime: 13384, // DNS query time\n  loadEventTime: 32, // 执行 onload 回调函数的时间\n  loadPageTime: 77772, // the time when the onload callback function is executed\n  redirectTime: 202, // redirection time\n  requestTime: 17151, // time when content loading is completed\n  timeToFirstByte: 63315, // the time taken to read the first byte of the page, that is, the time taken by the user to get your resources\n  unloadTime: 0 // time to unload the page\n}\n```\n\n#### getCustomLogByKeys(keys)\n\nget all custom log by keys\n\nreturn value：\n\n```javascript\n{\n  \"key1\": [\n    {\n      \"logTime\": 1584262658187,\n      \"url\": \"xxx\",\n      \"logSession\": \"xxx\",\n      \"logUser\": \"xxx\",\n      \"logKey\": \"key1\",\n      \"logType\": \"Custom Log\",\n      \"logContent\": {}\n    },\n    {\n      \"logTime\": 1584262658187,\n      \"url\": \"xxx\",\n      \"logSession\": \"xxx\",\n      \"logUser\": \"xxx\",\n      \"logKey\": \"key1\",\n      \"logType\": \"Custom Log\",\n      \"logContent\": {}\n    }\n  ],\n  \"key2\": []\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshadowings-zy%2Fshadow-tracker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshadowings-zy%2Fshadow-tracker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshadowings-zy%2Fshadow-tracker/lists"}