[{"data":1,"prerenderedAt":1816},["ShallowReactive",2],{"navigation-en":3,"content-urls":13,"pagesContext-en-2":224,"pagesContext-en-3":251,"authorsContext-en-jeroenbach":271,"postsContext-en-3-undefined":288},[4,7,10],{"label":5,"to":6},"Blog","\u002Fposts",{"label":8,"to":9},"Portfolio","\u002Fcontent\u002F20-portfolio",{"label":11,"to":12},"About","\u002Fcontent\u002F30-about",{"page":14,"blogPost":101,"blog":223},{"1":15,"10":37,"20":51,"30":65,"404":82},{"en":16,"fr":25,"nl":28,"de":31,"es":34},{"title":17,"path":18,"stem":19,"contentId":20,"url":21,"dateModified":22,"locale":23,"type":24},"Home","\u002Fcontent\u002Fhome","content\u002F1.home",1,"","2025-11-02T18:00:00","en","page",{"title":17,"path":18,"stem":19,"contentId":20,"url":26,"dateModified":22,"locale":27,"type":24},"\u002Ffr","fr",{"title":17,"path":18,"stem":19,"contentId":20,"url":29,"dateModified":22,"locale":30,"type":24},"\u002Fnl","nl",{"title":17,"path":18,"stem":19,"contentId":20,"url":32,"dateModified":22,"locale":33,"type":24},"\u002Fde","de",{"title":17,"path":18,"stem":19,"contentId":20,"url":35,"dateModified":22,"locale":36,"type":24},"\u002Fes","es",{"en":38,"fr":43,"nl":45,"de":47,"es":49},{"title":5,"path":39,"stem":40,"contentId":41,"url":6,"dateModified":42,"locale":23,"type":24},"\u002Fcontent\u002Fposts","content\u002F10.posts",10,"2025-10-26T18:00:00",{"title":5,"path":39,"stem":40,"contentId":41,"url":44,"dateModified":42,"locale":27,"type":24},"\u002Ffr\u002Farticles",{"title":5,"path":39,"stem":40,"contentId":41,"url":46,"dateModified":42,"locale":30,"type":24},"\u002Fnl\u002Fposts",{"title":5,"path":39,"stem":40,"contentId":41,"url":48,"dateModified":42,"locale":33,"type":24},"\u002Fde\u002Fposts",{"title":5,"path":39,"stem":40,"contentId":41,"url":50,"dateModified":42,"locale":36,"type":24},"\u002Fes\u002Farticulos",{"en":52,"fr":56,"nl":58,"de":60,"es":62},{"title":8,"path":53,"stem":54,"contentId":55,"url":9,"dateModified":42,"locale":23,"type":24},"\u002Fcontent\u002Fportfolio","content\u002F20.portfolio",20,{"title":8,"path":53,"stem":54,"contentId":55,"url":57,"dateModified":42,"locale":27,"type":24},"\u002Ffr\u002Fcontent\u002F20-portfolio",{"title":8,"path":53,"stem":54,"contentId":55,"url":59,"dateModified":42,"locale":30,"type":24},"\u002Fnl\u002Fcontent\u002F20-portfolio",{"title":8,"path":53,"stem":54,"contentId":55,"url":61,"dateModified":42,"locale":33,"type":24},"\u002Fde\u002Fcontent\u002F20-portfolio",{"title":63,"path":53,"stem":54,"contentId":55,"url":64,"dateModified":42,"locale":36,"type":24},"Portafolio","\u002Fes\u002Fcontent\u002F20-portafolio",{"en":66,"fr":70,"nl":73,"de":76,"es":79},{"title":11,"path":67,"stem":68,"contentId":69,"url":12,"dateModified":42,"locale":23,"type":24},"\u002Fcontent\u002Fabout","content\u002F30.about",30,{"title":71,"path":67,"stem":68,"contentId":69,"url":72,"dateModified":42,"locale":27,"type":24},"À propos","\u002Ffr\u002Fcontent\u002F30-a-propos",{"title":74,"path":67,"stem":68,"contentId":69,"url":75,"dateModified":42,"locale":30,"type":24},"Over","\u002Fnl\u002Fcontent\u002F30-over",{"title":77,"path":67,"stem":68,"contentId":69,"url":78,"dateModified":42,"locale":33,"type":24},"Über mich","\u002Fde\u002Fcontent\u002F30-uber-mich",{"title":80,"path":67,"stem":68,"contentId":69,"url":81,"dateModified":42,"locale":36,"type":24},"Acerca de","\u002Fes\u002Fcontent\u002F30-acerca-de",{"en":83,"fr":89,"nl":92,"de":95,"es":98},{"title":84,"path":85,"stem":86,"contentId":87,"url":88,"dateModified":22,"locale":23,"type":24},"Page not found","\u002Fcontent\u002Fpage-not-found","content\u002F404.page-not-found",404,"\u002Fcontent\u002F404-page-not-found",{"title":90,"path":85,"stem":86,"contentId":87,"url":91,"dateModified":22,"locale":27,"type":24},"Page non trouvée","\u002Ffr\u002Fcontent\u002F404-page-non-trouvee",{"title":93,"path":85,"stem":86,"contentId":87,"url":94,"dateModified":22,"locale":30,"type":24},"Pagina niet gevonden","\u002Fnl\u002Fcontent\u002F404-pagina-niet-gevonden",{"title":96,"path":85,"stem":86,"contentId":87,"url":97,"dateModified":22,"locale":33,"type":24},"Seite nicht gefunden","\u002Fde\u002Fcontent\u002F404-seite-nicht-gefunden",{"title":99,"path":85,"stem":86,"contentId":87,"url":100,"dateModified":22,"locale":36,"type":24},"Página no encontrada","\u002Fes\u002Fcontent\u002F404-pagina-no-encontrada",{"1":102,"2":126,"3":150,"4":175,"5":199},{"en":103,"fr":110,"nl":115,"de":118,"es":121},{"title":104,"path":105,"stem":106,"contentId":20,"dateModified":107,"url":108,"locale":23,"type":109},"Mastering Conditional Property Types with Vue 3.3 Generics","\u002Fposts\u002F1","posts\u002F1","2025-05-27T11:30:00","\u002Fposts\u002F1-mastering-conditional-property-types-with-vue-3_3-generics","blogPost",{"title":111,"path":112,"stem":113,"contentId":20,"dateModified":107,"url":114,"locale":27,"type":109},"Maîtriser les types de propriétés conditionnelles avec les génériques de Vue 3.3","\u002Farticles\u002F1","articles\u002F1","\u002Ffr\u002Farticles\u002F1-maitriser-les-types-de-proprietes-conditionnelles-avec-les-generiques-de-vue-3_3",{"title":116,"path":105,"stem":106,"contentId":20,"dateModified":107,"url":117,"locale":30,"type":109},"Conditionele Property Types beheersen met Vue 3.3 Generics","\u002Fnl\u002Fposts\u002F1-conditionele-property-types-beheersen-met-vue-3_3-generics",{"title":119,"path":105,"stem":106,"contentId":20,"dateModified":107,"url":120,"locale":33,"type":109},"Bedingte Property-Typen mit Vue 3.3 Generics meistern","\u002Fde\u002Fposts\u002F1-bedingte-property-typen-mit-vue-3_3-generics-meistern",{"title":122,"path":123,"stem":124,"contentId":20,"dateModified":107,"url":125,"locale":36,"type":109},"Dominar los tipos de propiedades condicionales con genéricos de Vue 3.3","\u002Farticulos\u002F1","articulos\u002F1","\u002Fes\u002Farticulos\u002F1-dominar-los-tipos-de-propiedades-condicionales-con-genericos-de-vue-3_3",{"en":127,"fr":134,"nl":139,"de":142,"es":145},{"title":128,"path":129,"stem":130,"contentId":131,"dateModified":132,"url":133,"locale":23,"type":109},"Ditching the Cookie Banners: Run Plausible Analytics on Azure Kubernetes","\u002Fposts\u002F2","posts\u002F2",2,"2025-10-04T13:00:00","\u002Fposts\u002F2-ditching-the-cookie-banners:-run-plausible-analytics-on-azure-kubernetes",{"title":135,"path":136,"stem":137,"contentId":131,"dateModified":132,"url":138,"locale":27,"type":109},"Éliminer les bannières de cookies: Exécutez Plausible Analytics sur Azure Kubernetes","\u002Farticles\u002F2","articles\u002F2","\u002Ffr\u002Farticles\u002F2-eliminer-les-bannieres-de-cookies:-executez-plausible-analytics-sur-azure-kubernetes",{"title":140,"path":129,"stem":130,"contentId":131,"dateModified":132,"url":141,"locale":30,"type":109},"Afscheid van Cookie Banners: Draai Plausible Analytics op Azure Kubernetes","\u002Fnl\u002Fposts\u002F2-afscheid-van-cookie-banners:-draai-plausible-analytics-op-azure-kubernetes",{"title":143,"path":129,"stem":130,"contentId":131,"dateModified":132,"url":144,"locale":33,"type":109},"Abschied von Cookie-Bannern: Plausible Analytics auf Azure Kubernetes betreiben","\u002Fde\u002Fposts\u002F2-abschied-von-cookie-bannern:-plausible-analytics-auf-azure-kubernetes-betreiben",{"title":146,"path":147,"stem":148,"contentId":131,"dateModified":132,"url":149,"locale":36,"type":109},"Eliminar los banners de cookies: Ejecuta Plausible Analytics en Azure Kubernetes","\u002Farticulos\u002F2","articulos\u002F2","\u002Fes\u002Farticulos\u002F2-eliminar-los-banners-de-cookies:-ejecuta-plausible-analytics-en-azure-kubernetes",{"en":151,"fr":158,"nl":164,"de":167,"es":170},{"title":152,"path":153,"stem":154,"contentId":155,"dateModified":156,"url":157,"locale":23,"type":109},"Track how many people read your articles, using Plausible.io, Vue.js and Azure functions","\u002Fposts\u002F3","posts\u002F3",3,"2025-08-03T15:45:00","\u002Fposts\u002F3-track-how-many-people-read-your-articles-using-plausible_io-vue_js-and-azure-functions",{"title":159,"path":160,"stem":161,"contentId":155,"dateModified":162,"url":163,"locale":27,"type":109},"Suivez combien de personnes lisent vos articles, en utilisant Plausible.io, Vue.js et Azure Functions","\u002Farticles\u002F3","articles\u002F3","2025-08-15:45:00","\u002Ffr\u002Farticles\u002F3-suivez-combien-de-personnes-lisent-vos-articles-en-utilisant-plausible_io-vue_js-et-azure-functions",{"title":165,"path":153,"stem":154,"contentId":155,"dateModified":156,"url":166,"locale":30,"type":109},"Volg hoeveel mensen je artikelen lezen, met Plausible.io, Vue.js en Azure functions","\u002Fnl\u002Fposts\u002F3-volg-hoeveel-mensen-je-artikelen-lezen-met-plausible_io-vue_js-en-azure-functions",{"title":168,"path":153,"stem":154,"contentId":155,"dateModified":156,"url":169,"locale":33,"type":109},"Verfolgen Sie, wie viele Menschen Ihre Artikel lesen, mit Plausible.io, Vue.js und Azure Functions","\u002Fde\u002Fposts\u002F3-verfolgen-sie-wie-viele-menschen-ihre-artikel-lesen-mit-plausible_io-vue_js-und-azure-functions",{"title":171,"path":172,"stem":173,"contentId":155,"dateModified":156,"url":174,"locale":36,"type":109},"Rastrea cuántas personas leen tus artículos, usando Plausible.io, Vue.js y funciones de Azure","\u002Farticulos\u002F3","articulos\u002F3","\u002Fes\u002Farticulos\u002F3-rastrea-cuantas-personas-leen-tus-articulos-usando-plausible_io-vue_js-y-funciones-de-azure",{"en":176,"fr":183,"nl":188,"de":191,"es":194},{"title":177,"path":178,"stem":179,"contentId":180,"dateModified":181,"url":182,"locale":23,"type":109},"Deploy a production-ready Kubernetes Cluster on Azure with Terraform","\u002Fposts\u002F4","posts\u002F4",4,"2025-12-06T21:00:00","\u002Fposts\u002F4-deploy-a-production-ready-kubernetes-cluster-on-azure-with-terraform",{"title":184,"path":185,"stem":186,"contentId":180,"dateModified":181,"url":187,"locale":27,"type":109},"Déployer un cluster Kubernetes prêt pour la production sur Azure avec Terraform","\u002Farticles\u002F4","articles\u002F4","\u002Ffr\u002Farticles\u002F4-deployer-un-cluster-kubernetes-pret-pour-la-production-sur-azure-avec-terraform",{"title":189,"path":178,"stem":179,"contentId":180,"dateModified":181,"url":190,"locale":30,"type":109},"Implementeer een productie-klaar Kubernetes Cluster op Azure met Terraform","\u002Fnl\u002Fposts\u002F4-implementeer-een-productie-klaar-kubernetes-cluster-op-azure-met-terraform",{"title":192,"path":178,"stem":179,"contentId":180,"dateModified":181,"url":193,"locale":33,"type":109},"Einen produktionsreifen Kubernetes-Cluster auf Azure mit Terraform bereitstellen","\u002Fde\u002Fposts\u002F4-einen-produktionsreifen-kubernetes-cluster-auf-azure-mit-terraform-bereitstellen",{"title":195,"path":196,"stem":197,"contentId":180,"dateModified":181,"url":198,"locale":36,"type":109},"Despliega un clúster de Kubernetes listo para producción en Azure con Terraform","\u002Farticulos\u002F4","articulos\u002F4","\u002Fes\u002Farticulos\u002F4-despliega-un-cluster-de-kubernetes-listo-para-produccion-en-azure-con-terraform",{"en":200,"fr":207,"nl":212,"de":215,"es":218},{"title":201,"path":202,"stem":203,"contentId":204,"dateModified":205,"url":206,"locale":23,"type":109},"Array to Map conversion in Typescript, with type safety","\u002Fposts\u002F5","posts\u002F5",5,"2025-09-29T21:00:00","\u002Fposts\u002F5-array-to-map-conversion-in-typescript-with-type-safety",{"title":208,"path":209,"stem":210,"contentId":204,"dateModified":205,"url":211,"locale":27,"type":109},"Conversion de tableau en Map en Typescript, avec sécurité des types","\u002Farticles\u002F5","articles\u002F5","\u002Ffr\u002Farticles\u002F5-conversion-de-tableau-en-map-en-typescript-avec-securite-des-types",{"title":213,"path":202,"stem":203,"contentId":204,"dateModified":205,"url":214,"locale":30,"type":109},"Array naar Map conversie in Typescript, met type veiligheid","\u002Fnl\u002Fposts\u002F5-array-naar-map-conversie-in-typescript-met-type-veiligheid",{"title":216,"path":202,"stem":203,"contentId":204,"dateModified":205,"url":217,"locale":33,"type":109},"Array zu Map Konvertierung in TypeScript, mit Typsicherheit","\u002Fde\u002Fposts\u002F5-array-zu-map-konvertierung-in-typescript-mit-typsicherheit",{"title":219,"path":220,"stem":221,"contentId":204,"dateModified":205,"url":222,"locale":36,"type":109},"Conversión de Array a Map en Typescript, con seguridad de tipos","\u002Farticulos\u002F5","articulos\u002F5","\u002Fes\u002Farticulos\u002F5-conversion-de-array-a-map-en-typescript-con-seguridad-de-tipos",{},{"id":225,"title":226,"body":227,"canonicalUrl":236,"company":236,"contentId":131,"dateModified":236,"datePublished":236,"description":233,"draft":237,"enableProse":237,"excludeFromNavigation":237,"extension":238,"imageAlt":236,"imageUrl":236,"meta":239,"navigation":245,"partial":245,"path":246,"seo":247,"slug":236,"stem":248,"url":249,"__hash__":250},"pages_en\u002Fcontent\u002F_footer.md","About Jeroen Bach",{"type":228,"value":229,"toc":234},"minimark",[230],[231,232,233],"p",{},"Designed in Figma and built with Vue.js, Nuxt.js and Tailwind CSS.\nDeployed via Azure Static Web App and Azure Functions.\nWebsite analytics are powered by Plausible Analytics, deployed using Azure Kubernetes Service.",{"title":21,"searchDepth":131,"depth":131,"links":235},[],null,false,"md",{"readingTime":240},{"text":241,"minutes":242,"time":243,"words":244},"1 min read",0.16,9600,32,true,"\u002Fcontent\u002F_footer",{"title":226,"description":233},"content\u002F_footer","\u002Fcontent\u002F2-about-jeroen-bach","tgPfOB73xkNtsI3Ers_EH08FHEHR7ko45cqNiVgrM0s",{"id":252,"title":253,"body":254,"canonicalUrl":236,"company":236,"contentId":155,"dateModified":236,"datePublished":236,"description":258,"draft":237,"enableProse":237,"excludeFromNavigation":237,"extension":238,"imageAlt":236,"imageUrl":236,"meta":261,"navigation":245,"partial":245,"path":266,"seo":267,"slug":236,"stem":268,"url":269,"__hash__":270},"pages_en\u002Fcontent\u002F_footer-about.md","Footer About",{"type":228,"value":255,"toc":259},[256],[231,257,258],{},"I'm a Software Engineer and Team Lead with over 15 years of professional experience.\nI'm passionate about solving complex problems through simple, elegant solutions.\nThis blog is where I share techniques and insights for building great software, inspired by real-world projects.",{"title":21,"searchDepth":131,"depth":131,"links":260},[],{"readingTime":262},{"text":241,"minutes":263,"time":264,"words":265},0.205,12300,41,"\u002Fcontent\u002F_footer-about",{"description":258},"content\u002F_footer-about","\u002Fcontent\u002F3-footer-about","49ofD3QAU2eKgnsoCR9zQhGEP7EECAsjUJeOHSF1GJI",{"id":272,"company":273,"extension":277,"fullName":278,"github":279,"homePage":280,"imageUrl":276,"linkedIn":281,"meta":282,"role":283,"stem":284,"twitter":285,"userName":286,"__hash__":287},"authors_en\u002Fauthors\u002Fjeroenbach.yaml",{"name":274,"url":275,"imageUrl":276},"Bach.Software","https:\u002F\u002Fbach.software","\u002FJEROEN-_A7R5652-HD-SQUARE-zoom.jpg","yaml","Jeroen Bach","https:\u002F\u002Fgithub.com\u002Fjeroenbach","https:\u002F\u002Fbach.software\u002Fpages\u002Fabout","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fjeroenbach\u002F",{},"Software Engineer \u002F Team Lead","authors\u002Fjeroenbach","https:\u002F\u002Fx.com\u002Fjeroenbach","jeroenbach","QjQ1vpL_EQbLZNaZdDNOjIkS-thm6oxHuAdoNIauNI8",{"id":289,"title":152,"authorName":286,"body":290,"canonicalUrl":236,"category":1787,"contentId":155,"dateModified":156,"datePublished":156,"description":1788,"draft":237,"excerpt":1789,"extension":238,"imageAlt":1801,"imagePosition":1802,"imageUrl":1803,"keywords":1804,"meta":1805,"navigation":245,"path":153,"readingTime":1806,"seo":1811,"slug":236,"stem":154,"url":157,"__hash__":1812,"author":1813},"posts_en\u002Fposts\u002F3.md",{"type":228,"value":291,"toc":1781},[292,312,315,322,327,338,378,381,386,394,398,401,406,411,422,435,439,442,444,461,465,474,1753,1767,1771,1774,1777],[231,293,294,295,299,300,303,304,307,308,311],{},"In the previous article you learned how to set up ",[296,297,298],"strong",{},"Plausible",", a ",[296,301,302],{},"privacy-friendly"," and ",[296,305,306],{},"affordable"," analytics solution.\nIn this article you'll learn how to use Plausible to collect the ",[296,309,310],{},"reading"," behavior of your visitors and display at the top of each of your articles how many people have read it.",[231,313,314],{},"Gathering information about your visitors is great, but having more insight into how many of them actually read your articles is even greater.\nTo do this, we need to define the progress your visitor is making in a few stages. We'll later turn these stages into goals, which will provide you with detailed information about how well your articles are doing.",[316,317],"post-image",{"alt":318,"caption":319,"css-class":320,"src":321},"Our read progress steps defined as goals in Plausible","Here you see how many people opened, peeked or read my first article","aspect-[735\u002F468]","posts\u002F3\u002Fplausibe-goals.png",[323,324,326],"h2",{"id":325},"tracking-reading-behavior","Tracking reading behavior",[231,328,329,330,333,334,337],{},"We will use a Medium.com inspired ",[296,331,332],{},"\"read time\"",". ",[296,335,336],{},"Medium.com"," calculates the read time based on the average reading speed of an adult (which is roughly 265 words per minute) and divides the total word count by this number.\nSo if your article will contain 2650 words, it will take your visitors roughly 10 minutes to read. When measuring the progress we'll define a few steps to indicate the progress, each representing a percentage of the total reading time:",[339,340,341,348,354,360,366,372],"ul",{},[342,343,344,347],"li",{},[296,345,346],{},"opened"," (0%): not started reading yet",[342,349,350,353],{},[296,351,352],{},"peeked"," (10%): just scrolled quickly through the article",[342,355,356,359],{},[296,357,358],{},"quarter-read"," (25%): started reading, but stopped at a quarter",[342,361,362,365],{},[296,363,364],{},"half-read"," (50%): read half way",[342,367,368,371],{},[296,369,370],{},"three-quarter-read"," (75%): read between half way or the whole article for fast readers",[342,373,374,377],{},[296,375,376],{},"read"," (100%): read your article with great attention",[231,379,380],{},"It's also important to keep a few scenarios in mind.",[382,383,385],"h4",{"id":384},"scenario-1-the-reader-gets-distracted-and-now-your-article-is-at-the-background","Scenario 1 => the reader gets distracted and now your article is at the background",[231,387,388,389,393],{},"This is easy to mitigate, we can use an event listener to detect document visibility changes and stop the timer: ",[390,391,392],"code",{},"document.addEventListener(\"visibilitychange\"",".",[382,395,397],{"id":396},"scenario-2-the-reader-walks-away-from-the-computer","Scenario 2 => the reader walks away from the computer",[231,399,400],{},"This is a bit harder to detect, but an option is to keep track of another indicator of 'reading', which is the scroll.\nSo next to the time progress, we also track scroll progress, and only when both time and scroll reach a certain level do we update the\nread progress to the next state.",[231,402,403],{},[296,404,405],{},"Click the button to see how you're doing, reading this page",[407,408],"page-read-progress",{":reading-time":409,":word-count":410},"readingTime.time","readingTime.words",[231,412,413,414],{},"To track the reading progress of your visitors, I've written a handy composable which you can view here: ",[415,416,421],"a",{":target":417,"href":418,"rel":419},"\\_blank","https:\u002F\u002Fgithub.com\u002Fjeroenbach\u002Fbach.software\u002Fblob\u002Fmain\u002Fsrc\u002Fapp\u002Fcomposables\u002FuseReadProgress.ts",[420],"nofollow","useReadProgress.ts",[231,423,424,425,430,431,434],{},"As reading progresses and the state changes, we update Plausible with custom events.\nTo do this I've written another composable, which you can view here: ",[415,426,429],{":target":417,"href":427,"rel":428},"https:\u002F\u002Fgithub.com\u002Fjeroenbach\u002Fbach.software\u002Fblob\u002Fmain\u002Fsrc\u002Fapp\u002Fcomposables\u002FuseReadProgressTracking.ts",[420],"useReadProgressTracking.ts",".\nIt converts the percentages from ",[390,432,433],{},"useReadProgress"," into the defined tracking goals and sends tracking events to Plausible.",[323,436,438],{"id":437},"create-goals-for-each-step-in-plausible","Create goals for each step in Plausible",[231,440,441],{},"When you define the above steps as goals in Plausible, you can see a nice funnel for each of your articles and how far your visitors get with them.",[316,443],{"alt":318,"caption":318,"css-class":320,"src":321},[231,445,446,447,450,451,454,455,457,458,460],{},"To set up goals in Plausible, go to ",[390,448,449],{},"Site Settings"," > ",[390,452,453],{},"Goals"," and add a goal for each of the steps (",[296,456,346],{},", ",[296,459,352],{},", etc).",[323,462,464],{"id":463},"reading-your-page-stats-from-plausible-using-an-azure-function","Reading your page stats from Plausible, using an Azure Function",[231,466,467,468,473],{},"Plausible provides a ",[415,469,472],{":target":417,"href":470,"rel":471},"https:\u002F\u002Fplausible.io\u002Fdocs\u002Fstats-api",[420],"Stats API"," that you can query to get for example the statistics of your created goals.\nSee the following code example, which shows how to query the API.",[475,476,477,1198,1371],"code-group",{},[478,479,484],"pre",{"className":480,"code":481,"filename":482,"language":483,"meta":21,"style":21},"language-csharp shiki shiki-themes github-light github-dark","public async Task\u003CPageReads> GetPageReads(string url)\n{\n    using var scope = _logger.BeginScope(new Dictionary\u003Cstring, object> { { \"url\", url } });\n\n    var uri = new Uri(url);\n    var domain = uri.Host;\n    var relativeUrl = uri.PathAndQuery;\n\n    var payload = new\n    {\n        site_id = domain,\n        metrics = new[] { \"visitors\" }, \u002F\u002F Get the unique number of Reading events\n        date_range = \"all\",\n        filters = new[]{\n            new List\u003Cobject> { \"contains\", \"event:page\", new[] { relativeUrl } },\n            new List\u003Cobject> { \"is\", \"event:goal\", new[] {\"read\", \"three-quarter-read\", \"half-read\", \"quarter-read\", \"peeked\", \"opened\"} },\n        },\n        dimensions = new[] { \"event:goal\" },\n    };\n\n    var jsonPayload = JsonSerializer.Serialize(payload);\n    _logger.LogInformation(\"Payload: {jsonPayload}\", jsonPayload);\n\n    var response = await SendRequest(jsonPayload);\n    var responseContent = await response.Content.ReadAsStringAsync();\n    _logger.LogInformation(\"Response: {responseContent}\", responseContent);\n\n    var queryResult = JsonSerializer.Deserialize\u003CQueryResult>(responseContent);\n    if (queryResult == null)\n    {\n        throw new InvalidOperationException(\"Failed to deserialize the response content.\");\n    }\n\n    var resultsDict = queryResult.Results.ToDictionary(x => x.Dimensions.First(), x => x.Metrics.First());\n\n    return new PageReads\n    {\n        Read = resultsDict.GetValueOrDefault(\"read\"),\n        ThreeQuarterRead = resultsDict.GetValueOrDefault(\"three-quarter-read\"),\n        HalfRead = resultsDict.GetValueOrDefault(\"half-read\"),\n        QuarterRead = resultsDict.GetValueOrDefault(\"quarter-read\"),\n        Peeked = resultsDict.GetValueOrDefault(\"peeked\"),\n        Opened = resultsDict.GetValueOrDefault(\"opened\"),\n    };\n}\n","C#","csharp",[390,485,486,526,531,578,583,602,615,628,633,646,651,663,686,700,713,744,803,809,826,832,836,855,872,877,896,917,932,937,960,978,982,1001,1006,1011,1056,1061,1072,1077,1098,1116,1134,1151,1169,1187,1192],{"__ignoreMap":21},[487,488,490,494,497,501,505,508,511,514,517,520,523],"span",{"class":489,"line":20},"line",[487,491,493],{"class":492},"szBVR","public",[487,495,496],{"class":492}," async",[487,498,500],{"class":499},"sScJk"," Task",[487,502,504],{"class":503},"sVt8B","\u003C",[487,506,507],{"class":499},"PageReads",[487,509,510],{"class":503},"> ",[487,512,513],{"class":499},"GetPageReads",[487,515,516],{"class":503},"(",[487,518,519],{"class":492},"string",[487,521,522],{"class":499}," url",[487,524,525],{"class":503},")\n",[487,527,528],{"class":489,"line":131},[487,529,530],{"class":503},"{\n",[487,532,533,536,539,542,545,548,551,553,556,559,561,563,565,568,571,575],{"class":489,"line":155},[487,534,535],{"class":492},"    using",[487,537,538],{"class":492}," var",[487,540,541],{"class":499}," scope",[487,543,544],{"class":492}," =",[487,546,547],{"class":503}," _logger.",[487,549,550],{"class":499},"BeginScope",[487,552,516],{"class":503},[487,554,555],{"class":492},"new",[487,557,558],{"class":499}," Dictionary",[487,560,504],{"class":503},[487,562,519],{"class":492},[487,564,457],{"class":503},[487,566,567],{"class":492},"object",[487,569,570],{"class":503},"> { { ",[487,572,574],{"class":573},"sZZnC","\"url\"",[487,576,577],{"class":503},", url } });\n",[487,579,580],{"class":489,"line":180},[487,581,582],{"emptyLinePlaceholder":245},"\n",[487,584,585,588,591,593,596,599],{"class":489,"line":204},[487,586,587],{"class":492},"    var",[487,589,590],{"class":499}," uri",[487,592,544],{"class":492},[487,594,595],{"class":492}," new",[487,597,598],{"class":499}," Uri",[487,600,601],{"class":503},"(url);\n",[487,603,605,607,610,612],{"class":489,"line":604},6,[487,606,587],{"class":492},[487,608,609],{"class":499}," domain",[487,611,544],{"class":492},[487,613,614],{"class":503}," uri.Host;\n",[487,616,618,620,623,625],{"class":489,"line":617},7,[487,619,587],{"class":492},[487,621,622],{"class":499}," relativeUrl",[487,624,544],{"class":492},[487,626,627],{"class":503}," uri.PathAndQuery;\n",[487,629,631],{"class":489,"line":630},8,[487,632,582],{"emptyLinePlaceholder":245},[487,634,636,638,641,643],{"class":489,"line":635},9,[487,637,587],{"class":492},[487,639,640],{"class":499}," payload",[487,642,544],{"class":492},[487,644,645],{"class":492}," new\n",[487,647,648],{"class":489,"line":41},[487,649,650],{"class":503},"    {\n",[487,652,654,657,660],{"class":489,"line":653},11,[487,655,656],{"class":503},"        site_id ",[487,658,659],{"class":492},"=",[487,661,662],{"class":503}," domain,\n",[487,664,666,669,671,673,676,679,682],{"class":489,"line":665},12,[487,667,668],{"class":503},"        metrics ",[487,670,659],{"class":492},[487,672,595],{"class":492},[487,674,675],{"class":503},"[] { ",[487,677,678],{"class":573},"\"visitors\"",[487,680,681],{"class":503}," }, ",[487,683,685],{"class":684},"sJ8bj","\u002F\u002F Get the unique number of Reading events\n",[487,687,689,692,694,697],{"class":489,"line":688},13,[487,690,691],{"class":503},"        date_range ",[487,693,659],{"class":492},[487,695,696],{"class":573}," \"all\"",[487,698,699],{"class":503},",\n",[487,701,703,706,708,710],{"class":489,"line":702},14,[487,704,705],{"class":503},"        filters ",[487,707,659],{"class":492},[487,709,595],{"class":492},[487,711,712],{"class":503},"[]{\n",[487,714,716,719,722,724,726,729,732,734,737,739,741],{"class":489,"line":715},15,[487,717,718],{"class":492},"            new",[487,720,721],{"class":499}," List",[487,723,504],{"class":503},[487,725,567],{"class":492},[487,727,728],{"class":503},"> { ",[487,730,731],{"class":573},"\"contains\"",[487,733,457],{"class":503},[487,735,736],{"class":573},"\"event:page\"",[487,738,457],{"class":503},[487,740,555],{"class":492},[487,742,743],{"class":503},"[] { relativeUrl } },\n",[487,745,747,749,751,753,755,757,760,762,765,767,769,772,775,777,780,782,785,787,790,792,795,797,800],{"class":489,"line":746},16,[487,748,718],{"class":492},[487,750,721],{"class":499},[487,752,504],{"class":503},[487,754,567],{"class":492},[487,756,728],{"class":503},[487,758,759],{"class":573},"\"is\"",[487,761,457],{"class":503},[487,763,764],{"class":573},"\"event:goal\"",[487,766,457],{"class":503},[487,768,555],{"class":492},[487,770,771],{"class":503},"[] {",[487,773,774],{"class":573},"\"read\"",[487,776,457],{"class":503},[487,778,779],{"class":573},"\"three-quarter-read\"",[487,781,457],{"class":503},[487,783,784],{"class":573},"\"half-read\"",[487,786,457],{"class":503},[487,788,789],{"class":573},"\"quarter-read\"",[487,791,457],{"class":503},[487,793,794],{"class":573},"\"peeked\"",[487,796,457],{"class":503},[487,798,799],{"class":573},"\"opened\"",[487,801,802],{"class":503},"} },\n",[487,804,806],{"class":489,"line":805},17,[487,807,808],{"class":503},"        },\n",[487,810,812,815,817,819,821,823],{"class":489,"line":811},18,[487,813,814],{"class":503},"        dimensions ",[487,816,659],{"class":492},[487,818,595],{"class":492},[487,820,675],{"class":503},[487,822,764],{"class":573},[487,824,825],{"class":503}," },\n",[487,827,829],{"class":489,"line":828},19,[487,830,831],{"class":503},"    };\n",[487,833,834],{"class":489,"line":55},[487,835,582],{"emptyLinePlaceholder":245},[487,837,839,841,844,846,849,852],{"class":489,"line":838},21,[487,840,587],{"class":492},[487,842,843],{"class":499}," jsonPayload",[487,845,544],{"class":492},[487,847,848],{"class":503}," JsonSerializer.",[487,850,851],{"class":499},"Serialize",[487,853,854],{"class":503},"(payload);\n",[487,856,858,861,864,866,869],{"class":489,"line":857},22,[487,859,860],{"class":503},"    _logger.",[487,862,863],{"class":499},"LogInformation",[487,865,516],{"class":503},[487,867,868],{"class":573},"\"Payload: {jsonPayload}\"",[487,870,871],{"class":503},", jsonPayload);\n",[487,873,875],{"class":489,"line":874},23,[487,876,582],{"emptyLinePlaceholder":245},[487,878,880,882,885,887,890,893],{"class":489,"line":879},24,[487,881,587],{"class":492},[487,883,884],{"class":499}," response",[487,886,544],{"class":492},[487,888,889],{"class":492}," await",[487,891,892],{"class":499}," SendRequest",[487,894,895],{"class":503},"(jsonPayload);\n",[487,897,899,901,904,906,908,911,914],{"class":489,"line":898},25,[487,900,587],{"class":492},[487,902,903],{"class":499}," responseContent",[487,905,544],{"class":492},[487,907,889],{"class":492},[487,909,910],{"class":503}," response.Content.",[487,912,913],{"class":499},"ReadAsStringAsync",[487,915,916],{"class":503},"();\n",[487,918,920,922,924,926,929],{"class":489,"line":919},26,[487,921,860],{"class":503},[487,923,863],{"class":499},[487,925,516],{"class":503},[487,927,928],{"class":573},"\"Response: {responseContent}\"",[487,930,931],{"class":503},", responseContent);\n",[487,933,935],{"class":489,"line":934},27,[487,936,582],{"emptyLinePlaceholder":245},[487,938,940,942,945,947,949,952,954,957],{"class":489,"line":939},28,[487,941,587],{"class":492},[487,943,944],{"class":499}," queryResult",[487,946,544],{"class":492},[487,948,848],{"class":503},[487,950,951],{"class":499},"Deserialize",[487,953,504],{"class":503},[487,955,956],{"class":499},"QueryResult",[487,958,959],{"class":503},">(responseContent);\n",[487,961,963,966,969,972,976],{"class":489,"line":962},29,[487,964,965],{"class":492},"    if",[487,967,968],{"class":503}," (queryResult ",[487,970,971],{"class":492},"==",[487,973,975],{"class":974},"sj4cs"," null",[487,977,525],{"class":503},[487,979,980],{"class":489,"line":69},[487,981,650],{"class":503},[487,983,985,988,990,993,995,998],{"class":489,"line":984},31,[487,986,987],{"class":492},"        throw",[487,989,595],{"class":492},[487,991,992],{"class":499}," InvalidOperationException",[487,994,516],{"class":503},[487,996,997],{"class":573},"\"Failed to deserialize the response content.\"",[487,999,1000],{"class":503},");\n",[487,1002,1003],{"class":489,"line":244},[487,1004,1005],{"class":503},"    }\n",[487,1007,1009],{"class":489,"line":1008},33,[487,1010,582],{"emptyLinePlaceholder":245},[487,1012,1014,1016,1019,1021,1024,1027,1029,1032,1035,1038,1041,1044,1046,1048,1051,1053],{"class":489,"line":1013},34,[487,1015,587],{"class":492},[487,1017,1018],{"class":499}," resultsDict",[487,1020,544],{"class":492},[487,1022,1023],{"class":503}," queryResult.Results.",[487,1025,1026],{"class":499},"ToDictionary",[487,1028,516],{"class":503},[487,1030,1031],{"class":499},"x",[487,1033,1034],{"class":492}," =>",[487,1036,1037],{"class":503}," x.Dimensions.",[487,1039,1040],{"class":499},"First",[487,1042,1043],{"class":503},"(), ",[487,1045,1031],{"class":499},[487,1047,1034],{"class":492},[487,1049,1050],{"class":503}," x.Metrics.",[487,1052,1040],{"class":499},[487,1054,1055],{"class":503},"());\n",[487,1057,1059],{"class":489,"line":1058},35,[487,1060,582],{"emptyLinePlaceholder":245},[487,1062,1064,1067,1069],{"class":489,"line":1063},36,[487,1065,1066],{"class":492},"    return",[487,1068,595],{"class":492},[487,1070,1071],{"class":499}," PageReads\n",[487,1073,1075],{"class":489,"line":1074},37,[487,1076,650],{"class":503},[487,1078,1080,1083,1085,1088,1091,1093,1095],{"class":489,"line":1079},38,[487,1081,1082],{"class":503},"        Read ",[487,1084,659],{"class":492},[487,1086,1087],{"class":503}," resultsDict.",[487,1089,1090],{"class":499},"GetValueOrDefault",[487,1092,516],{"class":503},[487,1094,774],{"class":573},[487,1096,1097],{"class":503},"),\n",[487,1099,1101,1104,1106,1108,1110,1112,1114],{"class":489,"line":1100},39,[487,1102,1103],{"class":503},"        ThreeQuarterRead ",[487,1105,659],{"class":492},[487,1107,1087],{"class":503},[487,1109,1090],{"class":499},[487,1111,516],{"class":503},[487,1113,779],{"class":573},[487,1115,1097],{"class":503},[487,1117,1119,1122,1124,1126,1128,1130,1132],{"class":489,"line":1118},40,[487,1120,1121],{"class":503},"        HalfRead ",[487,1123,659],{"class":492},[487,1125,1087],{"class":503},[487,1127,1090],{"class":499},[487,1129,516],{"class":503},[487,1131,784],{"class":573},[487,1133,1097],{"class":503},[487,1135,1136,1139,1141,1143,1145,1147,1149],{"class":489,"line":265},[487,1137,1138],{"class":503},"        QuarterRead ",[487,1140,659],{"class":492},[487,1142,1087],{"class":503},[487,1144,1090],{"class":499},[487,1146,516],{"class":503},[487,1148,789],{"class":573},[487,1150,1097],{"class":503},[487,1152,1154,1157,1159,1161,1163,1165,1167],{"class":489,"line":1153},42,[487,1155,1156],{"class":503},"        Peeked ",[487,1158,659],{"class":492},[487,1160,1087],{"class":503},[487,1162,1090],{"class":499},[487,1164,516],{"class":503},[487,1166,794],{"class":573},[487,1168,1097],{"class":503},[487,1170,1172,1175,1177,1179,1181,1183,1185],{"class":489,"line":1171},43,[487,1173,1174],{"class":503},"        Opened ",[487,1176,659],{"class":492},[487,1178,1087],{"class":503},[487,1180,1090],{"class":499},[487,1182,516],{"class":503},[487,1184,799],{"class":573},[487,1186,1097],{"class":503},[487,1188,1190],{"class":489,"line":1189},44,[487,1191,831],{"class":503},[487,1193,1195],{"class":489,"line":1194},45,[487,1196,1197],{"class":503},"}\n",[478,1199,1204],{"className":1200,"code":1201,"filename":1202,"language":1203,"meta":21,"style":21},"language-json shiki shiki-themes github-light github-dark","{\n  \"site_id\": \"{{site_id}}\",\n  \"metrics\": [\"visitors\"],\n  \"date_range\": \"all\",\n  \"filters\": [\n    [\"contains\", \"event:page\", [\"{{relative_url}}\"]],\n    [\n      \"is\",\n      \"event:goal\",\n      [\n        \"read\",\n        \"three-quarter-read\",\n        \"half-read\",\n        \"quarter-read\",\n        \"peeked\",\n        \"opened\"\n      ]\n    ]\n  ],\n  \"dimensions\": [\"event:goal\"]\n}\n","JSON request","json",[390,1205,1206,1210,1223,1236,1248,1256,1276,1281,1288,1295,1300,1307,1314,1321,1328,1335,1340,1345,1350,1355,1367],{"__ignoreMap":21},[487,1207,1208],{"class":489,"line":20},[487,1209,530],{"class":503},[487,1211,1212,1215,1218,1221],{"class":489,"line":131},[487,1213,1214],{"class":974},"  \"site_id\"",[487,1216,1217],{"class":503},": ",[487,1219,1220],{"class":573},"\"{{site_id}}\"",[487,1222,699],{"class":503},[487,1224,1225,1228,1231,1233],{"class":489,"line":155},[487,1226,1227],{"class":974},"  \"metrics\"",[487,1229,1230],{"class":503},": [",[487,1232,678],{"class":573},[487,1234,1235],{"class":503},"],\n",[487,1237,1238,1241,1243,1246],{"class":489,"line":180},[487,1239,1240],{"class":974},"  \"date_range\"",[487,1242,1217],{"class":503},[487,1244,1245],{"class":573},"\"all\"",[487,1247,699],{"class":503},[487,1249,1250,1253],{"class":489,"line":204},[487,1251,1252],{"class":974},"  \"filters\"",[487,1254,1255],{"class":503},": [\n",[487,1257,1258,1261,1263,1265,1267,1270,1273],{"class":489,"line":604},[487,1259,1260],{"class":503},"    [",[487,1262,731],{"class":573},[487,1264,457],{"class":503},[487,1266,736],{"class":573},[487,1268,1269],{"class":503},", [",[487,1271,1272],{"class":573},"\"{{relative_url}}\"",[487,1274,1275],{"class":503},"]],\n",[487,1277,1278],{"class":489,"line":617},[487,1279,1280],{"class":503},"    [\n",[487,1282,1283,1286],{"class":489,"line":630},[487,1284,1285],{"class":573},"      \"is\"",[487,1287,699],{"class":503},[487,1289,1290,1293],{"class":489,"line":635},[487,1291,1292],{"class":573},"      \"event:goal\"",[487,1294,699],{"class":503},[487,1296,1297],{"class":489,"line":41},[487,1298,1299],{"class":503},"      [\n",[487,1301,1302,1305],{"class":489,"line":653},[487,1303,1304],{"class":573},"        \"read\"",[487,1306,699],{"class":503},[487,1308,1309,1312],{"class":489,"line":665},[487,1310,1311],{"class":573},"        \"three-quarter-read\"",[487,1313,699],{"class":503},[487,1315,1316,1319],{"class":489,"line":688},[487,1317,1318],{"class":573},"        \"half-read\"",[487,1320,699],{"class":503},[487,1322,1323,1326],{"class":489,"line":702},[487,1324,1325],{"class":573},"        \"quarter-read\"",[487,1327,699],{"class":503},[487,1329,1330,1333],{"class":489,"line":715},[487,1331,1332],{"class":573},"        \"peeked\"",[487,1334,699],{"class":503},[487,1336,1337],{"class":489,"line":746},[487,1338,1339],{"class":573},"        \"opened\"\n",[487,1341,1342],{"class":489,"line":805},[487,1343,1344],{"class":503},"      ]\n",[487,1346,1347],{"class":489,"line":811},[487,1348,1349],{"class":503},"    ]\n",[487,1351,1352],{"class":489,"line":828},[487,1353,1354],{"class":503},"  ],\n",[487,1356,1357,1360,1362,1364],{"class":489,"line":55},[487,1358,1359],{"class":974},"  \"dimensions\"",[487,1361,1230],{"class":503},[487,1363,764],{"class":573},[487,1365,1366],{"class":503},"]\n",[487,1368,1369],{"class":489,"line":838},[487,1370,1197],{"class":503},[478,1372,1375],{"className":1200,"code":1373,"filename":1374,"language":1203,"meta":21,"style":21},"{\n  \"results\": [\n    { \"metrics\": [68], \"dimensions\": [\"opened\"] },\n    { \"metrics\": [45], \"dimensions\": [\"peeked\"] },\n    { \"metrics\": [40], \"dimensions\": [\"quarter-read\"] },\n    { \"metrics\": [31], \"dimensions\": [\"half-read\"] },\n    { \"metrics\": [21], \"dimensions\": [\"three-quarter-read\"] },\n    { \"metrics\": [14], \"dimensions\": [\"read\"] }\n  ],\n  \"meta\": {},\n  \"query\": {\n    \"site_id\": \"{{site_id}}\",\n    \"metrics\": [\"visitors\"],\n    \"date_range\": [\"2025-01-20T00:00:00+01:00\", \"2025-08-02T23:59:59+02:00\"],\n    \"filters\": [\n      [\"contains\", \"event:page\", [\"{{relative_url}}\"]],\n      [\n        \"is\",\n        \"event:goal\",\n        [\n          \"read\",\n          \"three-quarter-read\",\n          \"half-read\",\n          \"quarter-read\",\n          \"peeked\",\n          \"opened\"\n        ]\n      ]\n    ],\n    \"dimensions\": [\"event:goal\"],\n    \"order_by\": [[\"visitors\", \"desc\"]],\n    \"include\": {},\n    \"pagination\": { \"offset\": 0, \"limit\": 10000 }\n  }\n}\n","JSON response",[390,1376,1377,1381,1388,1414,1435,1456,1477,1498,1520,1524,1532,1540,1551,1562,1579,1586,1603,1607,1614,1621,1626,1633,1640,1647,1654,1661,1666,1671,1675,1680,1691,1708,1715,1744,1749],{"__ignoreMap":21},[487,1378,1379],{"class":489,"line":20},[487,1380,530],{"class":503},[487,1382,1383,1386],{"class":489,"line":131},[487,1384,1385],{"class":974},"  \"results\"",[487,1387,1255],{"class":503},[487,1389,1390,1393,1396,1398,1401,1404,1407,1409,1411],{"class":489,"line":155},[487,1391,1392],{"class":503},"    { ",[487,1394,1395],{"class":974},"\"metrics\"",[487,1397,1230],{"class":503},[487,1399,1400],{"class":974},"68",[487,1402,1403],{"class":503},"], ",[487,1405,1406],{"class":974},"\"dimensions\"",[487,1408,1230],{"class":503},[487,1410,799],{"class":573},[487,1412,1413],{"class":503},"] },\n",[487,1415,1416,1418,1420,1422,1425,1427,1429,1431,1433],{"class":489,"line":180},[487,1417,1392],{"class":503},[487,1419,1395],{"class":974},[487,1421,1230],{"class":503},[487,1423,1424],{"class":974},"45",[487,1426,1403],{"class":503},[487,1428,1406],{"class":974},[487,1430,1230],{"class":503},[487,1432,794],{"class":573},[487,1434,1413],{"class":503},[487,1436,1437,1439,1441,1443,1446,1448,1450,1452,1454],{"class":489,"line":204},[487,1438,1392],{"class":503},[487,1440,1395],{"class":974},[487,1442,1230],{"class":503},[487,1444,1445],{"class":974},"40",[487,1447,1403],{"class":503},[487,1449,1406],{"class":974},[487,1451,1230],{"class":503},[487,1453,789],{"class":573},[487,1455,1413],{"class":503},[487,1457,1458,1460,1462,1464,1467,1469,1471,1473,1475],{"class":489,"line":604},[487,1459,1392],{"class":503},[487,1461,1395],{"class":974},[487,1463,1230],{"class":503},[487,1465,1466],{"class":974},"31",[487,1468,1403],{"class":503},[487,1470,1406],{"class":974},[487,1472,1230],{"class":503},[487,1474,784],{"class":573},[487,1476,1413],{"class":503},[487,1478,1479,1481,1483,1485,1488,1490,1492,1494,1496],{"class":489,"line":617},[487,1480,1392],{"class":503},[487,1482,1395],{"class":974},[487,1484,1230],{"class":503},[487,1486,1487],{"class":974},"21",[487,1489,1403],{"class":503},[487,1491,1406],{"class":974},[487,1493,1230],{"class":503},[487,1495,779],{"class":573},[487,1497,1413],{"class":503},[487,1499,1500,1502,1504,1506,1509,1511,1513,1515,1517],{"class":489,"line":630},[487,1501,1392],{"class":503},[487,1503,1395],{"class":974},[487,1505,1230],{"class":503},[487,1507,1508],{"class":974},"14",[487,1510,1403],{"class":503},[487,1512,1406],{"class":974},[487,1514,1230],{"class":503},[487,1516,774],{"class":573},[487,1518,1519],{"class":503},"] }\n",[487,1521,1522],{"class":489,"line":635},[487,1523,1354],{"class":503},[487,1525,1526,1529],{"class":489,"line":41},[487,1527,1528],{"class":974},"  \"meta\"",[487,1530,1531],{"class":503},": {},\n",[487,1533,1534,1537],{"class":489,"line":653},[487,1535,1536],{"class":974},"  \"query\"",[487,1538,1539],{"class":503},": {\n",[487,1541,1542,1545,1547,1549],{"class":489,"line":665},[487,1543,1544],{"class":974},"    \"site_id\"",[487,1546,1217],{"class":503},[487,1548,1220],{"class":573},[487,1550,699],{"class":503},[487,1552,1553,1556,1558,1560],{"class":489,"line":688},[487,1554,1555],{"class":974},"    \"metrics\"",[487,1557,1230],{"class":503},[487,1559,678],{"class":573},[487,1561,1235],{"class":503},[487,1563,1564,1567,1569,1572,1574,1577],{"class":489,"line":702},[487,1565,1566],{"class":974},"    \"date_range\"",[487,1568,1230],{"class":503},[487,1570,1571],{"class":573},"\"2025-01-20T00:00:00+01:00\"",[487,1573,457],{"class":503},[487,1575,1576],{"class":573},"\"2025-08-02T23:59:59+02:00\"",[487,1578,1235],{"class":503},[487,1580,1581,1584],{"class":489,"line":715},[487,1582,1583],{"class":974},"    \"filters\"",[487,1585,1255],{"class":503},[487,1587,1588,1591,1593,1595,1597,1599,1601],{"class":489,"line":746},[487,1589,1590],{"class":503},"      [",[487,1592,731],{"class":573},[487,1594,457],{"class":503},[487,1596,736],{"class":573},[487,1598,1269],{"class":503},[487,1600,1272],{"class":573},[487,1602,1275],{"class":503},[487,1604,1605],{"class":489,"line":805},[487,1606,1299],{"class":503},[487,1608,1609,1612],{"class":489,"line":811},[487,1610,1611],{"class":573},"        \"is\"",[487,1613,699],{"class":503},[487,1615,1616,1619],{"class":489,"line":828},[487,1617,1618],{"class":573},"        \"event:goal\"",[487,1620,699],{"class":503},[487,1622,1623],{"class":489,"line":55},[487,1624,1625],{"class":503},"        [\n",[487,1627,1628,1631],{"class":489,"line":838},[487,1629,1630],{"class":573},"          \"read\"",[487,1632,699],{"class":503},[487,1634,1635,1638],{"class":489,"line":857},[487,1636,1637],{"class":573},"          \"three-quarter-read\"",[487,1639,699],{"class":503},[487,1641,1642,1645],{"class":489,"line":874},[487,1643,1644],{"class":573},"          \"half-read\"",[487,1646,699],{"class":503},[487,1648,1649,1652],{"class":489,"line":879},[487,1650,1651],{"class":573},"          \"quarter-read\"",[487,1653,699],{"class":503},[487,1655,1656,1659],{"class":489,"line":898},[487,1657,1658],{"class":573},"          \"peeked\"",[487,1660,699],{"class":503},[487,1662,1663],{"class":489,"line":919},[487,1664,1665],{"class":573},"          \"opened\"\n",[487,1667,1668],{"class":489,"line":934},[487,1669,1670],{"class":503},"        ]\n",[487,1672,1673],{"class":489,"line":939},[487,1674,1344],{"class":503},[487,1676,1677],{"class":489,"line":962},[487,1678,1679],{"class":503},"    ],\n",[487,1681,1682,1685,1687,1689],{"class":489,"line":69},[487,1683,1684],{"class":974},"    \"dimensions\"",[487,1686,1230],{"class":503},[487,1688,764],{"class":573},[487,1690,1235],{"class":503},[487,1692,1693,1696,1699,1701,1703,1706],{"class":489,"line":984},[487,1694,1695],{"class":974},"    \"order_by\"",[487,1697,1698],{"class":503},": [[",[487,1700,678],{"class":573},[487,1702,457],{"class":503},[487,1704,1705],{"class":573},"\"desc\"",[487,1707,1275],{"class":503},[487,1709,1710,1713],{"class":489,"line":244},[487,1711,1712],{"class":974},"    \"include\"",[487,1714,1531],{"class":503},[487,1716,1717,1720,1723,1726,1728,1731,1733,1736,1738,1741],{"class":489,"line":1008},[487,1718,1719],{"class":974},"    \"pagination\"",[487,1721,1722],{"class":503},": { ",[487,1724,1725],{"class":974},"\"offset\"",[487,1727,1217],{"class":503},[487,1729,1730],{"class":974},"0",[487,1732,457],{"class":503},[487,1734,1735],{"class":974},"\"limit\"",[487,1737,1217],{"class":503},[487,1739,1740],{"class":974},"10000",[487,1742,1743],{"class":503}," }\n",[487,1745,1746],{"class":489,"line":1013},[487,1747,1748],{"class":503},"  }\n",[487,1750,1751],{"class":489,"line":1058},[487,1752,1197],{"class":503},[231,1754,1755,1756,1761,1762],{},"See the full implementation here ",[415,1757,1760],{":target":417,"href":1758,"rel":1759},"https:\u002F\u002Fgithub.com\u002Fjeroenbach\u002Fbach.software\u002Fblob\u002Fd902b918933fdf2291dc896094b00ac13510e980\u002Fsrc\u002Fapi\u002FBach.Software.Infrastructure\u002FPlausibleAnalytics\u002FServices\u002FPlausibleService.cs#L35-L45",[420],"PlausibleService.cs","\nand the whole project here ",[415,1763,1766],{":target":417,"href":1764,"rel":1765},"https:\u002F\u002Fgithub.com\u002Fjeroenbach\u002Fbach.software\u002Ftree\u002Fmain\u002Fsrc\u002Fapi",[420],"Bach.Software.API",[323,1768,1770],{"id":1769},"conclusion","Conclusion",[231,1772,1773],{},"Understanding how deeply your audience engages with your content is far more meaningful than simply counting pageviews.\nWith just a few lines of code and the power of Plausible, you can now accurately track whether your readers are skimming or truly diving in.\nBy combining scroll behavior and reading time, you can fine-tune your editorial strategy and identify what resonates most.\nAnd because it's cookie-less, it aligns with modern privacy standards without sacrificing insight.",[231,1775,1776],{},"Whether you're a solo developer, a blogger, or managing a larger content platform, this approach gives you deep insights without the weight of invasive tracking.\nTry it out on your next post, you might be surprised by what your readers are really doing.",[1778,1779,1780],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}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);}",{"title":21,"searchDepth":131,"depth":131,"links":1782},[1783,1784,1785,1786],{"id":325,"depth":131,"text":326},{"id":437,"depth":131,"text":438},{"id":463,"depth":131,"text":464},{"id":1769,"depth":131,"text":1770},"Vue.js","Learn how to track the reading behavior of your visitors using Plausible.io, Vue.js, and Azure Functions. This article covers setting up goals in Plausible, tracking reading progress, and analyzing visitor engagement with your content.",{"type":228,"value":1790},[1791],[231,1792,294,1793,299,1795,303,1797,307,1799,311],{},[296,1794,298],{},[296,1796,302],{},[296,1798,306],{},[296,1800,310],{},"Reading funnel of your visitors","object-top","\u002Fposts\u002F3\u002Fcover.jpeg",[1787,482],{},{"text":1807,"minutes":1808,"time":1809,"words":1810},"5 min read",4.49,269400,898,{"title":152,"description":1788},"vSMky2_wo5gJbOHgKDUCDIQi8O_lGkxjesLV8eQUzQk",{"id":272,"company":1814,"extension":277,"fullName":278,"github":279,"homePage":280,"imageUrl":276,"linkedIn":281,"meta":1815,"role":283,"stem":284,"twitter":285,"userName":286,"__hash__":287},{"name":274,"url":275,"imageUrl":276},{},1781641709303]