[{"data":1,"prerenderedAt":2001},["ShallowReactive",2],{"blog-\u002Fblog\u002Fgetting-started-with-the-beacon-api":3,"blog-\u002Fblog\u002Fgetting-started-with-the-beacon-api-surround":1957,"blog-related":1968},{"id":4,"title":5,"body":6,"date":1945,"description":1946,"extension":1947,"meta":1948,"minutes":540,"navigation":280,"path":1949,"seo":1950,"stem":1951,"subtitle":1952,"tags":1953,"__hash__":1956},"blog\u002Fblog\u002Fgetting-started-with-the-beacon-api.md","Getting Started With The Beacon API",{"type":7,"value":8,"toc":1935},"minimark",[9,13,35,45,57,69,73,76,95,99,113,138,146,192,196,199,215,226,229,234,351,354,367,370,380,383,397,400,415,449,455,579,586,589,592,596,598,626,637,643,654,657,660,759,766,874,880,914,920,1119,1122,1402,1408,1412,1418,1587,1597,1603,1889,1892,1900,1903,1928,1931],[10,11,5],"h2",{"id":12},"getting-started-with-the-beacon-api",[14,15,16,17,24,25,30,31,34],"p",{},"The ",[18,19,23],"a",{"href":20,"rel":21},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FBeacon_API",[22],"nofollow","Beacon API"," is a web API avalible for developers to implement into their application. View full list of web APIs ",[18,26,29],{"href":27,"rel":28},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAP",[22],"here",". The ",[32,33,23],"code",{}," is a Web API useful for:",[36,37,38,42],"ul",{},[39,40,41],"li",{},"Analytics",[39,43,44],{},"Diagnostics",[10,46,48,49,52,53,56],{"id":47},"why-not-fetch-or-xmlhttprequest","Why  not ",[32,50,51],{},"fetch"," or ",[32,54,55],{},"XMLHttpRequest","?",[14,58,59,60,65,66,68],{},"As stated in the MDN Docs, the unfortunate truth is ",[18,61,64],{"href":62,"rel":63},"https:\u002F\u002Fdeveloper.chrome.com\u002Fmultidevice\u002Fuser-agent",[22],"User Agents"," will typically ignore ",[32,67,55],{}," made with an unload handler. Which is the handler we want to use before an individual leaves\u002Fnavigates away from the page.",[10,70,72],{"id":71},"overview","Overview?",[14,74,75],{},"In this article we will building a very basic analytics tracking library. The objective is to:",[77,78,79,82,85,88],"ol",{},[39,80,81],{},"Create a backend to capture the data and serve our index.html page",[39,83,84],{},"Track what element the end user clicked on and record it with a time stamp.",[39,86,87],{},"Store the data that is being generated on each click to a global object to store.",[39,89,90,91,94],{},"Before refreshing, or leaving the page send the data stored in the global object to the backend using the ",[32,92,93],{},"sendBeacon()"," method provided by the Beacon API.",[10,96,98],{"id":97},"setup","Setup",[77,100,101,110],{},[39,102,103,104,109],{},"First, make sure you have ",[18,105,108],{"href":106,"rel":107},"https:\u002F\u002Fnodejs.org\u002Fen\u002F",[22],"Node.js"," installed into your system.",[39,111,112],{},"Once Node is installed on your computer clone the project files:",[114,115,120],"pre",{"className":116,"code":117,"language":118,"meta":119,"style":119},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","git clone https:\u002F\u002Fgithub.com\u002FBboyAkers\u002FWebAPIs.git\n","bash","",[32,121,122],{"__ignoreMap":119},[123,124,127,131,135],"span",{"class":125,"line":126},"line",1,[123,128,130],{"class":129},"sBMFI","git",[123,132,134],{"class":133},"sfazB"," clone",[123,136,137],{"class":133}," https:\u002F\u002Fgithub.com\u002FBboyAkers\u002FWebAPIs.git\n",[14,139,140,141],{},"or\n",[18,142,145],{"href":143,"rel":144},"https:\u002F\u002Fgithub.com\u002FBboyAkers\u002FWebAPIs",[22],"Download Repo",[77,147,149,163],{"start":148},3,[39,150,151,152,156,157,156,160],{},"Navigate to the start folder. ",[153,154,155],"strong",{},"WebAPIs","->",[153,158,159],{},"beaconAPI",[153,161,162],{},"start",[39,164,165,166,169,170,173,174,177,178],{},"Open the terminal and install the dependencies ",[32,167,168],{},"npm install","\nWe've installed two dependencies. ",[32,171,172],{},"body-parser"," and ",[32,175,176],{},"express",".\n",[36,179,180,187],{},[39,181,182,183,186],{},"We will be using ",[32,184,185],{},"body-parse"," to parse the incoming POST request from our frontend.",[39,188,189,191],{},[32,190,176],{}," is the backend web framework we will be using to setup our server.",[10,193,195],{"id":194},"setting-up-our-server","Setting Up Our Server",[14,197,198],{},"Objective:",[36,200,201,204],{},[39,202,203],{},"Setup a basic express server",[39,205,206,207,210,211,214],{},"Serve our ",[32,208,209],{},"index.html"," inside of our ",[32,212,213],{},"public\u002F"," folder to the frontend",[14,216,217,218,221,222,225],{},"Navigate to the ",[153,219,220],{},"server.js"," file in the base directory of the ",[32,223,224],{},"start\u002F"," folder.",[14,227,228],{},"First we want to setup our basic express server",[14,230,231],{},[232,233,220],"em",{},[114,235,239],{"className":236,"code":237,"language":238,"meta":119,"style":119},"language-javascript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","const  express = require(\"express\");\n\nconst  app  =  express();\n\napp.listen(8081, () =>  console.log(\"Listening on 8081\"))\n","javascript",[32,240,241,275,282,299,304],{"__ignoreMap":119},[123,242,243,247,251,255,259,262,265,267,269,272],{"class":125,"line":126},[123,244,246],{"class":245},"spNyl","const",[123,248,250],{"class":249},"sTEyZ","  express ",[123,252,254],{"class":253},"sMK4o","=",[123,256,258],{"class":257},"s2Zo4"," require",[123,260,261],{"class":249},"(",[123,263,264],{"class":253},"\"",[123,266,176],{"class":133},[123,268,264],{"class":253},[123,270,271],{"class":249},")",[123,273,274],{"class":253},";\n",[123,276,278],{"class":125,"line":277},2,[123,279,281],{"emptyLinePlaceholder":280},true,"\n",[123,283,284,286,289,291,294,297],{"class":125,"line":148},[123,285,246],{"class":245},[123,287,288],{"class":249},"  app  ",[123,290,254],{"class":253},[123,292,293],{"class":257},"  express",[123,295,296],{"class":249},"()",[123,298,274],{"class":253},[123,300,302],{"class":125,"line":301},4,[123,303,281],{"emptyLinePlaceholder":280},[123,305,307,310,313,316,318,322,325,328,331,334,336,339,341,343,346,348],{"class":125,"line":306},5,[123,308,309],{"class":249},"app",[123,311,312],{"class":253},".",[123,314,315],{"class":257},"listen",[123,317,261],{"class":249},[123,319,321],{"class":320},"sbssI","8081",[123,323,324],{"class":253},",",[123,326,327],{"class":253}," ()",[123,329,330],{"class":245}," =>",[123,332,333],{"class":249},"  console",[123,335,312],{"class":253},[123,337,338],{"class":257},"log",[123,340,261],{"class":249},[123,342,264],{"class":253},[123,344,345],{"class":133},"Listening on 8081",[123,347,264],{"class":253},[123,349,350],{"class":249},"))\n",[14,352,353],{},"In your terminal run:",[114,355,357],{"className":116,"code":356,"language":118,"meta":119,"style":119},"node server.js\n",[32,358,359],{"__ignoreMap":119},[123,360,361,364],{"class":125,"line":126},[123,362,363],{"class":129},"node",[123,365,366],{"class":133}," server.js\n",[14,368,369],{},"We've now successfully setup our basic express server!",[14,371,372,373,376,377,312],{},"When we navigate to ",[32,374,375],{},"localhost:8081"," we should see the message: ",[32,378,379],{},"Cannot GET \u002F",[14,381,382],{},"What do we have to do to eliminate this error?",[77,384,385],{},[39,386,387,388,391,392],{},"We need to find something for our express app to do on ",[32,389,390],{},"\u002F"," our base directory.\n",[36,393,394],{},[39,395,396],{},"For example, serving our index.html to the frontend.",[14,398,399],{},"How do we serve our index.html from the servers side?",[14,401,402,403,408,409,411,412,414],{},"We are going to use ",[18,404,407],{"href":405,"rel":406},"https:\u002F\u002Fexpressjs.com\u002Fen\u002Fstarter\u002Fstatic-files.html",[22],"express static"," to serve the index.html, which is a static file. Our index.html file is located in the ",[32,410,213],{}," folder.  When using ",[32,413,407],{}," we need to establish what folder we want to use to serve our static content. Since all of our static content including our index.html is inside our public folder, we are going to specify the \"public\" folder.",[114,416,418],{"className":236,"code":417,"language":238,"meta":119,"style":119},"app.use(express.static('public'))\n",[32,419,420],{"__ignoreMap":119},[123,421,422,424,426,429,432,434,437,439,442,445,447],{"class":125,"line":126},[123,423,309],{"class":249},[123,425,312],{"class":253},[123,427,428],{"class":257},"use",[123,430,431],{"class":249},"(express",[123,433,312],{"class":253},[123,435,436],{"class":257},"static",[123,438,261],{"class":249},[123,440,441],{"class":253},"'",[123,443,444],{"class":133},"public",[123,446,441],{"class":253},[123,448,350],{"class":249},[14,450,451,452,454],{},"Our ",[232,453,220],{}," file should look quite similar to this:",[114,456,458],{"className":236,"code":457,"language":238,"meta":119,"style":119},"const express = require(\"express\");\n\nconst app = express();\n\n\u002F\u002Fserving the static content inside our public folder\napp.use(express.static('public'))\n\napp.listen(8081, () => console.log(\"Listening on 8081\"))\n",[32,459,460,483,487,503,507,513,538,543],{"__ignoreMap":119},[123,461,462,464,467,469,471,473,475,477,479,481],{"class":125,"line":126},[123,463,246],{"class":245},[123,465,466],{"class":249}," express ",[123,468,254],{"class":253},[123,470,258],{"class":257},[123,472,261],{"class":249},[123,474,264],{"class":253},[123,476,176],{"class":133},[123,478,264],{"class":253},[123,480,271],{"class":249},[123,482,274],{"class":253},[123,484,485],{"class":125,"line":277},[123,486,281],{"emptyLinePlaceholder":280},[123,488,489,491,494,496,499,501],{"class":125,"line":148},[123,490,246],{"class":245},[123,492,493],{"class":249}," app ",[123,495,254],{"class":253},[123,497,498],{"class":257}," express",[123,500,296],{"class":249},[123,502,274],{"class":253},[123,504,505],{"class":125,"line":301},[123,506,281],{"emptyLinePlaceholder":280},[123,508,509],{"class":125,"line":306},[123,510,512],{"class":511},"sHwdD","\u002F\u002Fserving the static content inside our public folder\n",[123,514,516,518,520,522,524,526,528,530,532,534,536],{"class":125,"line":515},6,[123,517,309],{"class":249},[123,519,312],{"class":253},[123,521,428],{"class":257},[123,523,431],{"class":249},[123,525,312],{"class":253},[123,527,436],{"class":257},[123,529,261],{"class":249},[123,531,441],{"class":253},[123,533,444],{"class":133},[123,535,441],{"class":253},[123,537,350],{"class":249},[123,539,541],{"class":125,"line":540},7,[123,542,281],{"emptyLinePlaceholder":280},[123,544,546,548,550,552,554,556,558,560,562,565,567,569,571,573,575,577],{"class":125,"line":545},8,[123,547,309],{"class":249},[123,549,312],{"class":253},[123,551,315],{"class":257},[123,553,261],{"class":249},[123,555,321],{"class":320},[123,557,324],{"class":253},[123,559,327],{"class":253},[123,561,330],{"class":245},[123,563,564],{"class":249}," console",[123,566,312],{"class":253},[123,568,338],{"class":257},[123,570,261],{"class":249},[123,572,264],{"class":253},[123,574,345],{"class":133},[123,576,264],{"class":253},[123,578,350],{"class":249},[14,580,581,582,585],{},"Navigate to ",[32,583,584],{},"localhost:8081\u002Findex.html"," in your browser.",[14,587,588],{},"You should now see our app.",[14,590,591],{},"Congratulations! You've successfully setup the server!",[10,593,595],{"id":594},"setting-up-our-analyticsjs-file","Setting Up Our Analytics.js File",[14,597,198],{},[36,599,600,607,618,621],{},[39,601,602,603,606],{},"Tie the ",[32,604,605],{},"analytics"," function on winow.onload window.unload.",[39,608,609,610],{},"Create an event that:\n",[36,611,612,615],{},[39,613,614],{},"detects what element a user clicks on when visiting the page",[39,616,617],{},"Create a timestamp to record what time the user clicked that element",[39,619,620],{},"Store the object that holds the clicked element and the timestamp into a global object.",[39,622,623,624],{},"Before leaving the page send all the stored data to the backend using the ",[32,625,23],{},[14,627,628,629,632,633,156,635,312],{},"Navigate to  our ",[153,630,631],{},"analytics.js"," file in ",[32,634,213],{},[32,636,631],{},[14,638,639,640,642],{},"Inside our ",[153,641,631],{}," file, the first thing we need to do is create an event handler that:",[36,644,645,648,651],{},[39,646,647],{},"captures the element we clicked on inside our document",[39,649,650],{},"the time we clicked on it",[39,652,653],{},"then push it to a global array that holds the history throughout the entire end users visit to the web page.",[14,655,656],{},"Let's do that!",[14,658,659],{},"First were capturing the element we clicked on and the time we clicked on it inside our document.",[114,661,663],{"className":236,"code":662,"language":238,"meta":119,"style":119},"document.addEventListener('click', (event) => {\n  {\n    clickedElement: event.target.outerHTML,\n    timestamp: new Date()\n  };\n})\n",[32,664,665,700,705,729,746,751],{"__ignoreMap":119},[123,666,667,670,672,675,677,679,682,684,686,689,693,695,697],{"class":125,"line":126},[123,668,669],{"class":249},"document",[123,671,312],{"class":253},[123,673,674],{"class":257},"addEventListener",[123,676,261],{"class":249},[123,678,441],{"class":253},[123,680,681],{"class":133},"click",[123,683,441],{"class":253},[123,685,324],{"class":253},[123,687,688],{"class":253}," (",[123,690,692],{"class":691},"sHdIc","event",[123,694,271],{"class":253},[123,696,330],{"class":245},[123,698,699],{"class":253}," {\n",[123,701,702],{"class":125,"line":277},[123,703,704],{"class":253},"  {\n",[123,706,707,710,713,716,718,721,723,726],{"class":125,"line":148},[123,708,709],{"class":129},"    clickedElement",[123,711,712],{"class":253},":",[123,714,715],{"class":249}," event",[123,717,312],{"class":253},[123,719,720],{"class":249},"target",[123,722,312],{"class":253},[123,724,725],{"class":249},"outerHTML",[123,727,728],{"class":253},",\n",[123,730,731,734,736,739,742],{"class":125,"line":301},[123,732,733],{"class":129},"    timestamp",[123,735,712],{"class":253},[123,737,738],{"class":253}," new",[123,740,741],{"class":257}," Date",[123,743,745],{"class":744},"swJcz","()\n",[123,747,748],{"class":125,"line":306},[123,749,750],{"class":253},"  };\n",[123,752,753,756],{"class":125,"line":515},[123,754,755],{"class":253},"}",[123,757,758],{"class":249},")\n",[14,760,761,762,765],{},"Next we need to create a ",[32,763,764],{},"dataHistory"," variable to store all data we capture from each click. Then push the captured data every time the user clicks inside the document.",[114,767,769],{"className":236,"code":768,"language":238,"meta":119,"style":119},"let dataHistory = [];\ndocument.addEventListener('click', (event) => {\n  dataHistory.push({\n    clickedElement: event.target.outerHTML,\n    timestamp: new Date()\n  });\n})\n",[32,770,771,786,814,829,847,859,868],{"__ignoreMap":119},[123,772,773,776,779,781,784],{"class":125,"line":126},[123,774,775],{"class":245},"let",[123,777,778],{"class":249}," dataHistory ",[123,780,254],{"class":253},[123,782,783],{"class":249}," []",[123,785,274],{"class":253},[123,787,788,790,792,794,796,798,800,802,804,806,808,810,812],{"class":125,"line":277},[123,789,669],{"class":249},[123,791,312],{"class":253},[123,793,674],{"class":257},[123,795,261],{"class":249},[123,797,441],{"class":253},[123,799,681],{"class":133},[123,801,441],{"class":253},[123,803,324],{"class":253},[123,805,688],{"class":253},[123,807,692],{"class":691},[123,809,271],{"class":253},[123,811,330],{"class":245},[123,813,699],{"class":253},[123,815,816,819,821,824,826],{"class":125,"line":148},[123,817,818],{"class":249},"  dataHistory",[123,820,312],{"class":253},[123,822,823],{"class":257},"push",[123,825,261],{"class":744},[123,827,828],{"class":253},"{\n",[123,830,831,833,835,837,839,841,843,845],{"class":125,"line":301},[123,832,709],{"class":744},[123,834,712],{"class":253},[123,836,715],{"class":249},[123,838,312],{"class":253},[123,840,720],{"class":249},[123,842,312],{"class":253},[123,844,725],{"class":249},[123,846,728],{"class":253},[123,848,849,851,853,855,857],{"class":125,"line":306},[123,850,733],{"class":744},[123,852,712],{"class":253},[123,854,738],{"class":253},[123,856,741],{"class":257},[123,858,745],{"class":744},[123,860,861,864,866],{"class":125,"line":515},[123,862,863],{"class":253},"  }",[123,865,271],{"class":744},[123,867,274],{"class":253},[123,869,870,872],{"class":125,"line":540},[123,871,755],{"class":253},[123,873,758],{"class":249},[14,875,876,877,879],{},"Now we need create our ",[32,878,605],{}," function. This function will;",[36,881,882,885,892,895,898,905],{},[39,883,884],{},"execute on window.load and window.unload",[39,886,887,888,891],{},"Check to see if our browser has the ",[32,889,890],{},"navigator.sendBeacon()"," method",[39,893,894],{},"If it doesn't it will simply return",[39,896,897],{},"If it does we will define the url we are sending our analytics data to the backend",[39,899,900,901,904],{},"Create a variable that will create a new ",[32,902,903],{},"Blob"," object that will hold our stringified JSON.",[39,906,907,908,911,912],{},"Send the data to the ",[32,909,910],{},"\u002Fanalytics"," endpoint using ",[32,913,890],{},[14,915,916,917,919],{},"What our ",[32,918,605],{}," methods should look like:",[114,921,923],{"className":236,"code":922,"language":238,"meta":119,"style":119},"window.onload = window.onunload = function analytics(event) {\n    if (!navigator.sendBeacon) return;\n\n    \u002F\u002F Url we are sending the data to\n    let url = \"http:\u002F\u002Flocalhost:8081\u002Fanalytics\";\n\n    \u002F\u002FCreate the data to send\n    const dataHistoryBlob = new Blob([JSON.stringify(dataHistory)], { type: 'application\u002Fjson' });\n\n    navigator.sendBeacon(url, dataHistoryBlob);\n};\n",[32,924,925,962,989,993,998,1018,1022,1027,1085,1090,1113],{"__ignoreMap":119},[123,926,927,930,932,935,937,940,942,945,948,951,954,956,958,960],{"class":125,"line":126},[123,928,929],{"class":249},"window",[123,931,312],{"class":253},[123,933,934],{"class":249},"onload ",[123,936,254],{"class":253},[123,938,939],{"class":249}," window",[123,941,312],{"class":253},[123,943,944],{"class":257},"onunload",[123,946,947],{"class":253}," =",[123,949,950],{"class":245}," function",[123,952,953],{"class":257}," analytics",[123,955,261],{"class":253},[123,957,692],{"class":691},[123,959,271],{"class":253},[123,961,699],{"class":253},[123,963,964,968,970,973,976,978,981,984,987],{"class":125,"line":277},[123,965,967],{"class":966},"s7zQu","    if",[123,969,688],{"class":744},[123,971,972],{"class":253},"!",[123,974,975],{"class":249},"navigator",[123,977,312],{"class":253},[123,979,980],{"class":249},"sendBeacon",[123,982,983],{"class":744},") ",[123,985,986],{"class":966},"return",[123,988,274],{"class":253},[123,990,991],{"class":125,"line":148},[123,992,281],{"emptyLinePlaceholder":280},[123,994,995],{"class":125,"line":301},[123,996,997],{"class":511},"    \u002F\u002F Url we are sending the data to\n",[123,999,1000,1003,1006,1008,1011,1014,1016],{"class":125,"line":306},[123,1001,1002],{"class":245},"    let",[123,1004,1005],{"class":249}," url",[123,1007,947],{"class":253},[123,1009,1010],{"class":253}," \"",[123,1012,1013],{"class":133},"http:\u002F\u002Flocalhost:8081\u002Fanalytics",[123,1015,264],{"class":253},[123,1017,274],{"class":253},[123,1019,1020],{"class":125,"line":515},[123,1021,281],{"emptyLinePlaceholder":280},[123,1023,1024],{"class":125,"line":540},[123,1025,1026],{"class":511},"    \u002F\u002FCreate the data to send\n",[123,1028,1029,1032,1035,1037,1039,1042,1045,1048,1050,1053,1055,1057,1060,1062,1065,1068,1070,1073,1076,1078,1081,1083],{"class":125,"line":545},[123,1030,1031],{"class":245},"    const",[123,1033,1034],{"class":249}," dataHistoryBlob",[123,1036,947],{"class":253},[123,1038,738],{"class":253},[123,1040,1041],{"class":257}," Blob",[123,1043,1044],{"class":744},"([",[123,1046,1047],{"class":249},"JSON",[123,1049,312],{"class":253},[123,1051,1052],{"class":257},"stringify",[123,1054,261],{"class":744},[123,1056,764],{"class":249},[123,1058,1059],{"class":744},")]",[123,1061,324],{"class":253},[123,1063,1064],{"class":253}," {",[123,1066,1067],{"class":744}," type",[123,1069,712],{"class":253},[123,1071,1072],{"class":253}," '",[123,1074,1075],{"class":133},"application\u002Fjson",[123,1077,441],{"class":253},[123,1079,1080],{"class":253}," }",[123,1082,271],{"class":744},[123,1084,274],{"class":253},[123,1086,1088],{"class":125,"line":1087},9,[123,1089,281],{"emptyLinePlaceholder":280},[123,1091,1093,1096,1098,1100,1102,1105,1107,1109,1111],{"class":125,"line":1092},10,[123,1094,1095],{"class":249},"    navigator",[123,1097,312],{"class":253},[123,1099,980],{"class":257},[123,1101,261],{"class":744},[123,1103,1104],{"class":249},"url",[123,1106,324],{"class":253},[123,1108,1034],{"class":249},[123,1110,271],{"class":744},[123,1112,274],{"class":253},[123,1114,1116],{"class":125,"line":1115},11,[123,1117,1118],{"class":253},"};\n",[14,1120,1121],{},"We've now completed our analytics.js file!\nThis is what our file should look like!",[114,1123,1125],{"className":236,"code":1124,"language":238,"meta":119,"style":119},"let dataHistory = [];\n\ndocument.addEventListener('click', (event) => {\n  dataHistory.push({\n    clickedElement: event.target.outerHTML,\n    timestamp: new Date()\n  });\n})\n\nwindow.onload = window.onunload = function analytics(event) {\n  if (!navigator.sendBeacon) return;\n\n  \u002F\u002F Url we are sending the data to\n  let url = \"http:\u002F\u002Flocalhost:8081\u002Fanalytics\";\n\n  \u002F\u002FCreate the data to send\n  const dataHistoryBlob = new Blob([JSON.stringify(dataHistory)], { type: 'application\u002Fjson' });\n\n  navigator.sendBeacon(url, dataHistoryBlob);\n};\n",[32,1126,1127,1139,1143,1171,1183,1201,1213,1221,1227,1231,1261,1282,1287,1293,1311,1316,1322,1370,1375,1397],{"__ignoreMap":119},[123,1128,1129,1131,1133,1135,1137],{"class":125,"line":126},[123,1130,775],{"class":245},[123,1132,778],{"class":249},[123,1134,254],{"class":253},[123,1136,783],{"class":249},[123,1138,274],{"class":253},[123,1140,1141],{"class":125,"line":277},[123,1142,281],{"emptyLinePlaceholder":280},[123,1144,1145,1147,1149,1151,1153,1155,1157,1159,1161,1163,1165,1167,1169],{"class":125,"line":148},[123,1146,669],{"class":249},[123,1148,312],{"class":253},[123,1150,674],{"class":257},[123,1152,261],{"class":249},[123,1154,441],{"class":253},[123,1156,681],{"class":133},[123,1158,441],{"class":253},[123,1160,324],{"class":253},[123,1162,688],{"class":253},[123,1164,692],{"class":691},[123,1166,271],{"class":253},[123,1168,330],{"class":245},[123,1170,699],{"class":253},[123,1172,1173,1175,1177,1179,1181],{"class":125,"line":301},[123,1174,818],{"class":249},[123,1176,312],{"class":253},[123,1178,823],{"class":257},[123,1180,261],{"class":744},[123,1182,828],{"class":253},[123,1184,1185,1187,1189,1191,1193,1195,1197,1199],{"class":125,"line":306},[123,1186,709],{"class":744},[123,1188,712],{"class":253},[123,1190,715],{"class":249},[123,1192,312],{"class":253},[123,1194,720],{"class":249},[123,1196,312],{"class":253},[123,1198,725],{"class":249},[123,1200,728],{"class":253},[123,1202,1203,1205,1207,1209,1211],{"class":125,"line":515},[123,1204,733],{"class":744},[123,1206,712],{"class":253},[123,1208,738],{"class":253},[123,1210,741],{"class":257},[123,1212,745],{"class":744},[123,1214,1215,1217,1219],{"class":125,"line":540},[123,1216,863],{"class":253},[123,1218,271],{"class":744},[123,1220,274],{"class":253},[123,1222,1223,1225],{"class":125,"line":545},[123,1224,755],{"class":253},[123,1226,758],{"class":249},[123,1228,1229],{"class":125,"line":1087},[123,1230,281],{"emptyLinePlaceholder":280},[123,1232,1233,1235,1237,1239,1241,1243,1245,1247,1249,1251,1253,1255,1257,1259],{"class":125,"line":1092},[123,1234,929],{"class":249},[123,1236,312],{"class":253},[123,1238,934],{"class":249},[123,1240,254],{"class":253},[123,1242,939],{"class":249},[123,1244,312],{"class":253},[123,1246,944],{"class":257},[123,1248,947],{"class":253},[123,1250,950],{"class":245},[123,1252,953],{"class":257},[123,1254,261],{"class":253},[123,1256,692],{"class":691},[123,1258,271],{"class":253},[123,1260,699],{"class":253},[123,1262,1263,1266,1268,1270,1272,1274,1276,1278,1280],{"class":125,"line":1115},[123,1264,1265],{"class":966},"  if",[123,1267,688],{"class":744},[123,1269,972],{"class":253},[123,1271,975],{"class":249},[123,1273,312],{"class":253},[123,1275,980],{"class":249},[123,1277,983],{"class":744},[123,1279,986],{"class":966},[123,1281,274],{"class":253},[123,1283,1285],{"class":125,"line":1284},12,[123,1286,281],{"emptyLinePlaceholder":280},[123,1288,1290],{"class":125,"line":1289},13,[123,1291,1292],{"class":511},"  \u002F\u002F Url we are sending the data to\n",[123,1294,1296,1299,1301,1303,1305,1307,1309],{"class":125,"line":1295},14,[123,1297,1298],{"class":245},"  let",[123,1300,1005],{"class":249},[123,1302,947],{"class":253},[123,1304,1010],{"class":253},[123,1306,1013],{"class":133},[123,1308,264],{"class":253},[123,1310,274],{"class":253},[123,1312,1314],{"class":125,"line":1313},15,[123,1315,281],{"emptyLinePlaceholder":280},[123,1317,1319],{"class":125,"line":1318},16,[123,1320,1321],{"class":511},"  \u002F\u002FCreate the data to send\n",[123,1323,1325,1328,1330,1332,1334,1336,1338,1340,1342,1344,1346,1348,1350,1352,1354,1356,1358,1360,1362,1364,1366,1368],{"class":125,"line":1324},17,[123,1326,1327],{"class":245},"  const",[123,1329,1034],{"class":249},[123,1331,947],{"class":253},[123,1333,738],{"class":253},[123,1335,1041],{"class":257},[123,1337,1044],{"class":744},[123,1339,1047],{"class":249},[123,1341,312],{"class":253},[123,1343,1052],{"class":257},[123,1345,261],{"class":744},[123,1347,764],{"class":249},[123,1349,1059],{"class":744},[123,1351,324],{"class":253},[123,1353,1064],{"class":253},[123,1355,1067],{"class":744},[123,1357,712],{"class":253},[123,1359,1072],{"class":253},[123,1361,1075],{"class":133},[123,1363,441],{"class":253},[123,1365,1080],{"class":253},[123,1367,271],{"class":744},[123,1369,274],{"class":253},[123,1371,1373],{"class":125,"line":1372},18,[123,1374,281],{"emptyLinePlaceholder":280},[123,1376,1378,1381,1383,1385,1387,1389,1391,1393,1395],{"class":125,"line":1377},19,[123,1379,1380],{"class":249},"  navigator",[123,1382,312],{"class":253},[123,1384,980],{"class":257},[123,1386,261],{"class":744},[123,1388,1104],{"class":249},[123,1390,324],{"class":253},[123,1392,1034],{"class":249},[123,1394,271],{"class":744},[123,1396,274],{"class":253},[123,1398,1400],{"class":125,"line":1399},20,[123,1401,1118],{"class":253},[14,1403,1404,1405,1407],{},"There's one last thing we haven't done. In our url variable we send the data to a backend endpoint we haven't defined yet, ",[32,1406,910],{},". Let's go to our server.js file to create that endpoint and make sure it can parse the data it's receiving.",[10,1409,1411],{"id":1410},"creating-the-analytics-endpoint","Creating The \"\u002Fanalytics\" Endpoint",[14,1413,1414,1415,1417],{},"In our server.js file let's create the ",[32,1416,910],{}," endpoint.",[114,1419,1421],{"className":236,"code":1420,"language":238,"meta":119,"style":119},"const express = require(\"express\");\n\nconst app = express();\n\napp.post(\"\u002Fanalytics\", (req, res) => {\n  console.log(req.body);\n  res.sendStatus(204);\n});\napp.listen(8081, () => console.log(\"Listening on 8081\"));\n",[32,1422,1423,1445,1449,1463,1467,1502,1523,1542,1550],{"__ignoreMap":119},[123,1424,1425,1427,1429,1431,1433,1435,1437,1439,1441,1443],{"class":125,"line":126},[123,1426,246],{"class":245},[123,1428,466],{"class":249},[123,1430,254],{"class":253},[123,1432,258],{"class":257},[123,1434,261],{"class":249},[123,1436,264],{"class":253},[123,1438,176],{"class":133},[123,1440,264],{"class":253},[123,1442,271],{"class":249},[123,1444,274],{"class":253},[123,1446,1447],{"class":125,"line":277},[123,1448,281],{"emptyLinePlaceholder":280},[123,1450,1451,1453,1455,1457,1459,1461],{"class":125,"line":148},[123,1452,246],{"class":245},[123,1454,493],{"class":249},[123,1456,254],{"class":253},[123,1458,498],{"class":257},[123,1460,296],{"class":249},[123,1462,274],{"class":253},[123,1464,1465],{"class":125,"line":301},[123,1466,281],{"emptyLinePlaceholder":280},[123,1468,1469,1471,1473,1476,1478,1480,1482,1484,1486,1488,1491,1493,1496,1498,1500],{"class":125,"line":306},[123,1470,309],{"class":249},[123,1472,312],{"class":253},[123,1474,1475],{"class":257},"post",[123,1477,261],{"class":249},[123,1479,264],{"class":253},[123,1481,910],{"class":133},[123,1483,264],{"class":253},[123,1485,324],{"class":253},[123,1487,688],{"class":253},[123,1489,1490],{"class":691},"req",[123,1492,324],{"class":253},[123,1494,1495],{"class":691}," res",[123,1497,271],{"class":253},[123,1499,330],{"class":245},[123,1501,699],{"class":253},[123,1503,1504,1506,1508,1510,1512,1514,1516,1519,1521],{"class":125,"line":515},[123,1505,333],{"class":249},[123,1507,312],{"class":253},[123,1509,338],{"class":257},[123,1511,261],{"class":744},[123,1513,1490],{"class":249},[123,1515,312],{"class":253},[123,1517,1518],{"class":249},"body",[123,1520,271],{"class":744},[123,1522,274],{"class":253},[123,1524,1525,1528,1530,1533,1535,1538,1540],{"class":125,"line":540},[123,1526,1527],{"class":249},"  res",[123,1529,312],{"class":253},[123,1531,1532],{"class":257},"sendStatus",[123,1534,261],{"class":744},[123,1536,1537],{"class":320},"204",[123,1539,271],{"class":744},[123,1541,274],{"class":253},[123,1543,1544,1546,1548],{"class":125,"line":545},[123,1545,755],{"class":253},[123,1547,271],{"class":249},[123,1549,274],{"class":253},[123,1551,1552,1554,1556,1558,1560,1562,1564,1566,1568,1570,1572,1574,1576,1578,1580,1582,1585],{"class":125,"line":1087},[123,1553,309],{"class":249},[123,1555,312],{"class":253},[123,1557,315],{"class":257},[123,1559,261],{"class":249},[123,1561,321],{"class":320},[123,1563,324],{"class":253},[123,1565,327],{"class":253},[123,1567,330],{"class":245},[123,1569,564],{"class":249},[123,1571,312],{"class":253},[123,1573,338],{"class":257},[123,1575,261],{"class":249},[123,1577,264],{"class":253},[123,1579,345],{"class":133},[123,1581,264],{"class":253},[123,1583,1584],{"class":249},"))",[123,1586,274],{"class":253},[14,1588,1589,1590,1592,1593,1596],{},"If we log the data won't be able to see anything due to express. All of our data is being passed through the body of our request. Unfortunately express itself can't parse data from the body so we have to use the ",[32,1591,172],{}," package from npm. Fortunately when we did an npm install setting up the project we already added the package as a dependency. Feel free to check your ",[153,1594,1595],{},"package.json"," for reference.",[14,1598,1599,1600,1602],{},"Now we need to add body parser to our server and use it to parse the json data being sent to the ",[32,1601,910],{}," endpoint. Our file should look like this.",[114,1604,1606],{"className":236,"code":1605,"language":238,"meta":119,"style":119},"const express = require(\"express\");\nconst bodyParser = require(\"body-parser\");\nconst app = express();\n\n\u002F\u002F parse application\u002Fx-www-form-urlencoded\napp.use(bodyParser.urlencoded({ extended: false }));\n\n\u002F\u002F parse application\u002Fjson\napp.use(bodyParser.json());\n\n\u002F\u002Fserving the static content inside our public folder\napp.use(express.static('public'));\n\napp.post(\"\u002Fanalytics\", (req, res) => {\n  console.log(req.body);\n  res.sendStatus(204);\n});\napp.listen(8081, () => console.log(\"Listening on 8081\"))\n",[32,1607,1608,1630,1653,1667,1671,1676,1712,1716,1721,1741,1745,1749,1775,1779,1811,1831,1847,1855],{"__ignoreMap":119},[123,1609,1610,1612,1614,1616,1618,1620,1622,1624,1626,1628],{"class":125,"line":126},[123,1611,246],{"class":245},[123,1613,466],{"class":249},[123,1615,254],{"class":253},[123,1617,258],{"class":257},[123,1619,261],{"class":249},[123,1621,264],{"class":253},[123,1623,176],{"class":133},[123,1625,264],{"class":253},[123,1627,271],{"class":249},[123,1629,274],{"class":253},[123,1631,1632,1634,1637,1639,1641,1643,1645,1647,1649,1651],{"class":125,"line":277},[123,1633,246],{"class":245},[123,1635,1636],{"class":249}," bodyParser ",[123,1638,254],{"class":253},[123,1640,258],{"class":257},[123,1642,261],{"class":249},[123,1644,264],{"class":253},[123,1646,172],{"class":133},[123,1648,264],{"class":253},[123,1650,271],{"class":249},[123,1652,274],{"class":253},[123,1654,1655,1657,1659,1661,1663,1665],{"class":125,"line":148},[123,1656,246],{"class":245},[123,1658,493],{"class":249},[123,1660,254],{"class":253},[123,1662,498],{"class":257},[123,1664,296],{"class":249},[123,1666,274],{"class":253},[123,1668,1669],{"class":125,"line":301},[123,1670,281],{"emptyLinePlaceholder":280},[123,1672,1673],{"class":125,"line":306},[123,1674,1675],{"class":511},"\u002F\u002F parse application\u002Fx-www-form-urlencoded\n",[123,1677,1678,1680,1682,1684,1687,1689,1692,1694,1697,1700,1702,1706,1708,1710],{"class":125,"line":515},[123,1679,309],{"class":249},[123,1681,312],{"class":253},[123,1683,428],{"class":257},[123,1685,1686],{"class":249},"(bodyParser",[123,1688,312],{"class":253},[123,1690,1691],{"class":257},"urlencoded",[123,1693,261],{"class":249},[123,1695,1696],{"class":253},"{",[123,1698,1699],{"class":744}," extended",[123,1701,712],{"class":253},[123,1703,1705],{"class":1704},"sfNiH"," false",[123,1707,1080],{"class":253},[123,1709,1584],{"class":249},[123,1711,274],{"class":253},[123,1713,1714],{"class":125,"line":540},[123,1715,281],{"emptyLinePlaceholder":280},[123,1717,1718],{"class":125,"line":545},[123,1719,1720],{"class":511},"\u002F\u002F parse application\u002Fjson\n",[123,1722,1723,1725,1727,1729,1731,1733,1736,1739],{"class":125,"line":1087},[123,1724,309],{"class":249},[123,1726,312],{"class":253},[123,1728,428],{"class":257},[123,1730,1686],{"class":249},[123,1732,312],{"class":253},[123,1734,1735],{"class":257},"json",[123,1737,1738],{"class":249},"())",[123,1740,274],{"class":253},[123,1742,1743],{"class":125,"line":1092},[123,1744,281],{"emptyLinePlaceholder":280},[123,1746,1747],{"class":125,"line":1115},[123,1748,512],{"class":511},[123,1750,1751,1753,1755,1757,1759,1761,1763,1765,1767,1769,1771,1773],{"class":125,"line":1284},[123,1752,309],{"class":249},[123,1754,312],{"class":253},[123,1756,428],{"class":257},[123,1758,431],{"class":249},[123,1760,312],{"class":253},[123,1762,436],{"class":257},[123,1764,261],{"class":249},[123,1766,441],{"class":253},[123,1768,444],{"class":133},[123,1770,441],{"class":253},[123,1772,1584],{"class":249},[123,1774,274],{"class":253},[123,1776,1777],{"class":125,"line":1289},[123,1778,281],{"emptyLinePlaceholder":280},[123,1780,1781,1783,1785,1787,1789,1791,1793,1795,1797,1799,1801,1803,1805,1807,1809],{"class":125,"line":1295},[123,1782,309],{"class":249},[123,1784,312],{"class":253},[123,1786,1475],{"class":257},[123,1788,261],{"class":249},[123,1790,264],{"class":253},[123,1792,910],{"class":133},[123,1794,264],{"class":253},[123,1796,324],{"class":253},[123,1798,688],{"class":253},[123,1800,1490],{"class":691},[123,1802,324],{"class":253},[123,1804,1495],{"class":691},[123,1806,271],{"class":253},[123,1808,330],{"class":245},[123,1810,699],{"class":253},[123,1812,1813,1815,1817,1819,1821,1823,1825,1827,1829],{"class":125,"line":1313},[123,1814,333],{"class":249},[123,1816,312],{"class":253},[123,1818,338],{"class":257},[123,1820,261],{"class":744},[123,1822,1490],{"class":249},[123,1824,312],{"class":253},[123,1826,1518],{"class":249},[123,1828,271],{"class":744},[123,1830,274],{"class":253},[123,1832,1833,1835,1837,1839,1841,1843,1845],{"class":125,"line":1318},[123,1834,1527],{"class":249},[123,1836,312],{"class":253},[123,1838,1532],{"class":257},[123,1840,261],{"class":744},[123,1842,1537],{"class":320},[123,1844,271],{"class":744},[123,1846,274],{"class":253},[123,1848,1849,1851,1853],{"class":125,"line":1324},[123,1850,755],{"class":253},[123,1852,271],{"class":249},[123,1854,274],{"class":253},[123,1856,1857,1859,1861,1863,1865,1867,1869,1871,1873,1875,1877,1879,1881,1883,1885,1887],{"class":125,"line":1372},[123,1858,309],{"class":249},[123,1860,312],{"class":253},[123,1862,315],{"class":257},[123,1864,261],{"class":249},[123,1866,321],{"class":320},[123,1868,324],{"class":253},[123,1870,327],{"class":253},[123,1872,330],{"class":245},[123,1874,564],{"class":249},[123,1876,312],{"class":253},[123,1878,338],{"class":257},[123,1880,261],{"class":249},[123,1882,264],{"class":253},[123,1884,345],{"class":133},[123,1886,264],{"class":253},[123,1888,350],{"class":249},[14,1890,1891],{},"If we save and restart our server we can click on several elements, refresh the page, exit the page, or navigate to a different website, we should see the data being sent and logged to our server. We have now successfully build a very simple use case for the beacon API!",[14,1893,1894,1895],{},"Side note: To check to see what data is being sent to the backend on the browsers side. You can preserve the logs in the network tab.\n",[1896,1897],"img",{"alt":1898,"src":1899},"Picture of preserve log in the Network Tab of Chrome Developer Tools","https:\u002F\u002Fdev-to-uploads.s3.amazonaws.com\u002Fi\u002Fljxj0xfw3dtk4dicp9cz.PNG",[14,1901,1902],{},"Challenges:\nExpand upon the project by:",[36,1904,1905,1915,1918,1925],{},[39,1906,1907,1908,1911,1912,1914],{},"Separating the business logic(our click event) into our ",[153,1909,1910],{},"index.js"," file and have it import and use our ",[153,1913,631],{}," file.",[39,1916,1917],{},"Expand upon the current tracking capabilities by adding unique sessions.",[39,1919,1920,1921,1924],{},"Clean up the element retrieval data. We currently use ",[32,1922,1923],{},".outerHTML"," see if there are better ways to find the elements we clicked on. :)",[39,1926,1927],{},"Create a pop up to give users the option to accept or decline tracking.",[14,1929,1930],{},"Happy coding!",[1932,1933,1934],"style",{},"html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":119,"searchDepth":277,"depth":277,"links":1936},[1937,1938,1940,1941,1942,1943,1944],{"id":12,"depth":277,"text":5},{"id":47,"depth":277,"text":1939},"Why  not fetch or XMLHttpRequest?",{"id":71,"depth":277,"text":72},{"id":97,"depth":277,"text":98},{"id":194,"depth":277,"text":195},{"id":594,"depth":277,"text":595},{"id":1410,"depth":277,"text":1411},"2020-06-25","A tutorial of the Beacon API for web","md",{},"\u002Fblog\u002Fgetting-started-with-the-beacon-api",{"title":5,"description":1946},"blog\u002Fgetting-started-with-the-beacon-api","Web API Series:",[238,1954,1955],"web api","tutorial","VhtD2hXUEdAncVr7dCapATY09Ti5U6GKhDlCj_gS1yw",[1958,1963],{"title":1959,"path":1960,"stem":1961,"description":1962,"children":-1},"Demystifying the ECMAScript Spec: Array.prototype.push","\u002Fblog\u002Fdemystifying-the-ecmascript-spec-array-push","blog\u002Fdemystifying-the-ecmascript-spec-array-push","A step-by-step tutorial on translating the ECMAScript specification for Array.prototype.push into working JavaScript.",{"title":1964,"path":1965,"stem":1966,"description":1967,"children":-1},"Let's build a Github Profile Search Web App","\u002Fblog\u002Flets-build-a-github-profile-search-web-app","blog\u002Flets-build-a-github-profile-search-web-app","A tutorial for using the Github API",[1969,1974,1982,1984,1989,1996],{"title":1959,"date":1970,"tags":1971,"path":1960},"2026-09-22",[1972,1973,238,1955],"intermediate","ecmascript",{"title":1975,"date":1976,"tags":1977,"path":1981},"V-Card In Depth","2023-03-08",[1978,1979,1980,238],"beginners","vuetify","vue","\u002Fblog\u002Fv-card-in-depth",{"title":5,"date":1945,"tags":1983,"path":1949},[238,1954,1955],{"title":1985,"date":1986,"tags":1987,"path":1988},"What is Tree Shaking","2020-05-29",[1978,1979,1980,238],"\u002Fblog\u002Fwhat-is-tree-shaking",{"title":1990,"date":1991,"tags":1992,"path":1995},"What is a CLI","2020-05-11",[1993,1979,1994],"vue3","typescript","\u002Fblog\u002Fwhat-is-a-cli",{"title":1964,"date":1997,"tags":1998,"path":1965},"2019-07-03",[1999,238,2000,1955],"web project","github api",1790258055668]