From 83625644ea3f123a74ce3fc88e4c919cc96b6c26 Mon Sep 17 00:00:00 2001 From: Cotes Chung <11371340+cotes2020@users.noreply.github.com> Date: Sun, 4 Jun 2023 10:56:31 +0800 Subject: [PATCH] refactor(core): remove GA page views report (#1071) - Google Analytics superProxy has been archived and is no longer maintained. - Google Analytics UA end of life. See also: https://support.google.com/analytics/answer/11583528?hl=en --- _config.yml | 4 - _data/origin/basic.yml | 3 - _data/origin/cors.yml | 3 - _includes/head.html | 21 -- _includes/js-selector.html | 7 - _javascript/modules/components/pageviews.js | 248 -------------------- _javascript/modules/plugins.js | 1 - _javascript/post.js | 2 - _layouts/post.html | 10 - _posts/2021-01-03-enable-google-pv.md | 243 ------------------- _sass/addon/commons.scss | 4 - assets/js/data/swcache.js | 6 +- assets/lib | 2 +- 13 files changed, 2 insertions(+), 552 deletions(-) delete mode 100644 _javascript/modules/components/pageviews.js delete mode 100644 _posts/2021-01-03-enable-google-pv.md diff --git a/_config.yml b/_config.yml index 25ab1a4..9ffdf0e 100644 --- a/_config.yml +++ b/_config.yml @@ -54,10 +54,6 @@ google_site_verification: # fill in to your verification string google_analytics: id: # fill in your Google Analytics ID - # Google Analytics pageviews report settings - pv: - proxy_endpoint: # fill in the Google Analytics superProxy endpoint of Google App Engine - cache_path: # the local PV cache data, friendly to visitors from GFW region # Prefer color scheme setting. # diff --git a/_data/origin/basic.yml b/_data/origin/basic.yml index 3327e48..14d865a 100644 --- a/_data/origin/basic.yml +++ b/_data/origin/basic.yml @@ -31,9 +31,6 @@ dayjs: relativeTime: /assets/lib/dayjs/plugin/relativeTime.min.js localizedFormat: /assets/lib/dayjs/plugin/localizedFormat.min.js -countup: - js: /assets/lib/countup.js/countUp.min.js - magnific-popup: css: /assets/lib/magnific-popup/magnific-popup.css js: /assets/lib/magnific-popup/jquery.magnific-popup.min.js diff --git a/_data/origin/cors.yml b/_data/origin/cors.yml index 857f477..2d28bba 100644 --- a/_data/origin/cors.yml +++ b/_data/origin/cors.yml @@ -42,9 +42,6 @@ dayjs: relativeTime: https://cdn.jsdelivr.net/npm/dayjs@1.11.7/plugin/relativeTime.min.js localizedFormat: https://cdn.jsdelivr.net/npm/dayjs@1.11.7/plugin/localizedFormat.min.js -countup: - js: https://cdn.jsdelivr.net/npm/countup.js@1.9.3/dist/countUp.min.js - magnific-popup: css: https://cdn.jsdelivr.net/npm/magnific-popup@1.1.0/dist/magnific-popup.min.css js: https://cdn.jsdelivr.net/npm/magnific-popup@1.1.0/dist/jquery.magnific-popup.min.js diff --git a/_includes/head.html b/_includes/head.html index 0c85fe1..577c67b 100644 --- a/_includes/head.html +++ b/_includes/head.html @@ -11,16 +11,6 @@ content="width=device-width, user-scalable=no initial-scale=1, shrink-to-fit=no, viewport-fit=cover" > - {% if page.layout == 'home' or page.layout == 'post' %} - {% if site.google_analytics.pv.proxy_endpoint %} - - {% endif %} - - {% if site.google_analytics.pv.cache_path %} - - {% endif %} - {% endif %} - {% capture seo_tags %} {% seo title=false %} {% endcapture %} @@ -76,17 +66,6 @@ - - {% if site.google_analytics.pv.proxy_endpoint %} - {% assign proxy_url = site.google_analytics.pv.proxy_endpoint - | replace: 'https://', '' - | split: '/' - | first - | prepend: 'https://' - %} - - - {% endif %} {% endif %} diff --git a/_includes/js-selector.html b/_includes/js-selector.html index 177aaf2..f6c8e9d 100644 --- a/_includes/js-selector.html +++ b/_includes/js-selector.html @@ -11,13 +11,6 @@ -{% if page.layout == 'post' %} - {% if site.google_analytics.pv.proxy_endpoint or site.google_analytics.pv.cache_path %} - - {% assign urls = urls | append: ',' | append: site.data.origin[type].countup.js %} - {% endif %} -{% endif %} - {% if page.layout == 'post' or page.layout == 'page' or page.layout == 'home' %} {% assign urls = urls | append: ',' | append: site.data.origin[type].lazysizes.js %} diff --git a/_javascript/modules/components/pageviews.js b/_javascript/modules/components/pageviews.js deleted file mode 100644 index d07d4aa..0000000 --- a/_javascript/modules/components/pageviews.js +++ /dev/null @@ -1,248 +0,0 @@ -/** - * Count page views form GA or local cache file. - * - * Dependencies: - * - jQuery - * - countUp.js - */ - -const getInitStatus = (function () { - let hasInit = false; - return () => { - let ret = hasInit; - if (!hasInit) { - hasInit = true; - } - return ret; - }; -})(); - -const PvOpts = (function () { - function getContent(selector) { - return $(selector).attr('content'); - } - - function hasContent(selector) { - let content = getContent(selector); - return typeof content !== 'undefined' && content !== false; - } - - return { - getProxyMeta() { - return getContent('meta[name=pv-proxy-endpoint]'); - }, - getLocalMeta() { - return getContent('meta[name=pv-cache-path]'); - }, - hasProxyMeta() { - return hasContent('meta[name=pv-proxy-endpoint]'); - }, - hasLocalMeta() { - return hasContent('meta[name=pv-cache-path]'); - } - }; -})(); - -const PvStorage = (function () { - const Keys = { - KEY_PV: 'pv', - KEY_PV_SRC: 'pv_src', - KEY_CREATION: 'pv_created_date' - }; - - const Source = { - LOCAL: 'same-origin', - PROXY: 'cors' - }; - - function get(key) { - return localStorage.getItem(key); - } - - function set(key, val) { - localStorage.setItem(key, val); - } - - function saveCache(pv, src) { - set(Keys.KEY_PV, pv); - set(Keys.KEY_PV_SRC, src); - set(Keys.KEY_CREATION, new Date().toJSON()); - } - - return { - keysCount() { - return Object.keys(Keys).length; - }, - hasCache() { - return localStorage.getItem(Keys.KEY_PV) !== null; - }, - getCache() { - return JSON.parse(localStorage.getItem(Keys.KEY_PV)); - }, - saveLocalCache(pv) { - saveCache(pv, Source.LOCAL); - }, - saveProxyCache(pv) { - saveCache(pv, Source.PROXY); - }, - isExpired() { - let date = new Date(get(Keys.KEY_CREATION)); - date.setHours(date.getHours() + 1); // per hour - return Date.now() >= date.getTime(); - }, - isFromLocal() { - return get(Keys.KEY_PV_SRC) === Source.LOCAL; - }, - isFromProxy() { - return get(Keys.KEY_PV_SRC) === Source.PROXY; - }, - newerThan(pv) { - return ( - PvStorage.getCache().totalsForAllResults['ga:pageviews'] > - pv.totalsForAllResults['ga:pageviews'] - ); - }, - inspectKeys() { - if (localStorage.length !== PvStorage.keysCount()) { - localStorage.clear(); - return; - } - - for (let i = 0; i < localStorage.length; i++) { - const key = localStorage.key(i); - switch (key) { - case Keys.KEY_PV: - case Keys.KEY_PV_SRC: - case Keys.KEY_CREATION: - break; - default: - localStorage.clear(); - return; - } - } - } - }; -})(); /* PvStorage */ - -function countUp(min, max, destId) { - if (min < max) { - let numAnim = new CountUp(destId, min, max); - if (!numAnim.error) { - numAnim.start(); - } else { - console.error(numAnim.error); - } - } -} - -function countPV(path, rows) { - let count = 0; - - if (typeof rows !== 'undefined') { - for (let i = 0; i < rows.length; ++i) { - const gaPath = rows[parseInt(i, 10)][0]; - if (gaPath === path) { - /* path format see: site.permalink */ - count += parseInt(rows[parseInt(i, 10)][1], 10); - break; - } - } - } - - return count; -} - -function tacklePV(rows, path, elem, hasInit) { - let count = countPV(path, rows); - count = count === 0 ? 1 : count; - - if (!hasInit) { - elem.text(new Intl.NumberFormat().format(count)); - } else { - const initCount = parseInt(elem.text().replace(/,/g, ''), 10); - if (count > initCount) { - countUp(initCount, count, elem.attr('id')); - } - } -} - -function displayPageviews(data) { - if (typeof data === 'undefined') { - return; - } - - let hasInit = getInitStatus(); - const rows = data.rows; /* could be undefined */ - - if ($('.post').length > 0) { - /* the post */ - const path = window.location.pathname; - tacklePV(rows, path, $('#pv'), hasInit); - } -} - -function fetchProxyPageviews() { - if (PvOpts.hasProxyMeta()) { - $.ajax({ - type: 'GET', - url: PvOpts.getProxyMeta(), - dataType: 'jsonp', - success: (data) => { - displayPageviews(data); - PvStorage.saveProxyCache(JSON.stringify(data)); - }, - error: (jqXHR, textStatus, errorThrown) => { - console.log( - 'Failed to load pageviews from proxy server: ' + errorThrown - ); - } - }); - } -} - -function fetchLocalPageviews(hasCache = false) { - return fetch(PvOpts.getLocalMeta()) - .then((response) => response.json()) - .then((data) => { - if (hasCache) { - // The cache from the proxy will sometimes be more recent than the local one - if (PvStorage.isFromProxy() && PvStorage.newerThan(data)) { - return; - } - } - displayPageviews(data); - PvStorage.saveLocalCache(JSON.stringify(data)); - }); -} - -export function initPageviews() { - if ($('.pageviews').length <= 0) { - return; - } - - PvStorage.inspectKeys(); - - if (PvStorage.hasCache()) { - displayPageviews(PvStorage.getCache()); - - if (PvStorage.isExpired()) { - if (PvOpts.hasLocalMeta()) { - fetchLocalPageviews(true).then(fetchProxyPageviews); - } else { - fetchProxyPageviews(); - } - } else { - if (PvStorage.isFromLocal()) { - fetchProxyPageviews(); - } - } - } else { - // no cached - - if (PvOpts.hasLocalMeta()) { - fetchLocalPageviews().then(fetchProxyPageviews); - } else { - fetchProxyPageviews(); - } - } -} diff --git a/_javascript/modules/plugins.js b/_javascript/modules/plugins.js index 2bb844a..fa7a7dd 100644 --- a/_javascript/modules/plugins.js +++ b/_javascript/modules/plugins.js @@ -3,5 +3,4 @@ export { initClipboard } from './components/clipboard'; export { imgLazy } from './components/img-lazyload'; export { imgPopup } from './components/img-popup'; export { initLocaleDatetime } from './components/locale-datetime'; -export { initPageviews } from './components/pageviews'; export { toc } from './components/toc'; diff --git a/_javascript/post.js b/_javascript/post.js index c77d6e1..9a5a61b 100644 --- a/_javascript/post.js +++ b/_javascript/post.js @@ -4,7 +4,6 @@ import { imgPopup, initLocaleDatetime, initClipboard, - initPageviews, toc } from './modules/plugins'; @@ -16,4 +15,3 @@ imgPopup(); initLocaleDatetime(); initClipboard(); toc(); -initPageviews(); diff --git a/_layouts/post.html b/_layouts/post.html index 3cd6de7..1821975 100644 --- a/_layouts/post.html +++ b/_layouts/post.html @@ -71,16 +71,6 @@ tail_includes:
- - {% if site.google_analytics.pv.proxy_endpoint or site.google_analytics.pv.cache_path %} - - - - - {{ site.data.locales[lang].post.pageview_measure }} - - {% endif %} - {% include read-time.html content=content prompt=true lang=lang %}
diff --git a/_posts/2021-01-03-enable-google-pv.md b/_posts/2021-01-03-enable-google-pv.md deleted file mode 100644 index 73cf13c..0000000 --- a/_posts/2021-01-03-enable-google-pv.md +++ /dev/null @@ -1,243 +0,0 @@ ---- -title: Enable Google Page Views -author: sille_bille -date: 2021-01-03 18:32:00 -0500 -categories: [Blogging, Tutorial] -tags: [google analytics, pageviews] ---- - -> The content of this post applies only to [_Universal Analytics property_](https://support.google.com/analytics/answer/10220206) (UA), not [_Google Analytics 4_](https://support.google.com/analytics/answer/10089681) (GA 4). In addition, since [UA is about to be deprecated on Jul 1, 2023](https://support.google.com/analytics/answer/11583528), the Page Views feature of [_Chirpy_][chirpy-homepage] will also be deprecated at that time. -{: .prompt-danger } - -This post is to enable Page Views on the [**Chirpy**][chirpy-homepage] theme based blog that you just built. This requires technical knowledge and it's recommended to keep the `google_analytics.pv.*` empty unless you have a good reason. If your website has low traffic, the page views count would discourage you to write more blogs. With that said, let's start with the setup. - -## Set up Google Analytics - -### Create GA account and property - -First, you need to set up your account on Google analytics. While you create your account, you must create your first **Property** as well. - -1. Head to and click on **Start Measuring** -2. Enter your desired _Account Name_ and choose the desired checkboxes -3. Enter your desired _Property Name_. This is the name of the tracker project that appears on your Google Analytics dashboard -4. Enter the required information _About your business_ -5. Hit _Create_ and accept any license popup to set up your Google Analytics account and create your property - -### Create Data Stream - -With your property created, you now need to set up Data Stream to track your blog traffic. After you signup, the prompt should automatically take you to create your first **Data Stream**. If not, follow these steps: - -1. Go to **Admin** on the left column -2. Select the desired property from the drop-down on the second column -3. Click on **Data Streams** -4. Add a stream and click on **Web** -5. Enter your blog's URL - -It should look like this: - -![google-analytics-data-stream](/posts/20210103/01-google-analytics-data-stream.png){: width="1086" height="542"} - -Now, click on the new data stream and grab the **Measurement ID**. It should look something like `G-V6XXXXXXXX`. Copy this to your `_config.yml`{: .filepath} file: - -```yaml -google_analytics: - id: 'G-V6XXXXXXX' # fill in your Google Analytics ID - # Google Analytics pageviews report settings - pv: - proxy_endpoint: # fill in the Google Analytics superProxy endpoint of Google App Engine - cache_path: # the local PV cache data, friendly to visitors from GFW region -``` -{: file="_config.yml"} - -When you push these changes to your blog, you should start seeing the traffic on your Google Analytics. Play around with the Google Analytics dashboard to get familiar with the options available as it takes like 5 mins to pick up your changes. You should now be able to monitor your traffic in real time. - -![google-analytics-realtime](/posts/20210103/02-google-analytics-realtime.png){: width="616" height="557"} - -## Setup Page Views - -There is a detailed [tutorial](https://developers.google.com/analytics/solutions/google-analytics-super-proxy) available to set up Google Analytics superProxy. But, if you are interested to just quickly get your Chirpy-based blog display page views, follow along. These steps were tested on a Linux machine. If you are running Windows, you can use the Git bash terminal to run Unix-like commands. - -### Setup Google App Engine - -1. Visit - -2. Click on **Create Application** - -3. Click on **Create Project** - -4. Enter the name and choose the data center close to you - -5. Select **Python** language and **Standard** environment - -6. Enable billing account. Yeah, you have to link your credit card. But, you won't be billed unless you exceed your free quota. For a simple blog, the free quota is more than sufficient. - -7. Go to your App Engine dashboard on your browser and select **API & Services** from the left navigation menu - -8. Click on **Enable APIs and Services** button on the top - -9. Enable the following APIs: _Google Analytics API_ - -10. On the left, Click on _OAuth Consent Screen_ and accept **Configure Consent Screen**. Select **External** since your blog is probably hosted for the public. Click on **Publish** under _Publishing Status_ - -11. Click on **Credentials** on the left and create a new **OAuth Client IDs** credential. Make sure to add an entry under `Authorized redirect URIs` that matches: `https://..r.appspot.com/admin/auth` - -12. Note down the **Your Client ID** and **Your Client Secret**. You'll need this in the next section. - -13. Download and install the cloud SDK for your platform: - -14. Run the following commands: - - ```console - [root@bc96abf71ef8 /]# gcloud init - - ~snip~ - - Go to the following link in your browser: - - https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=XYZ.apps.googleusercontent.com&redirect_uri=ABCDEFG - - Enter verification code: - - You are logged in as: [blah_blah@gmail.com]. - - Pick cloud project to use: - [1] chirpy-test-300716 - [2] Create a new project - Please enter numeric choice or text value (must exactly match list - item): 1 - - - [root@bc96abf71ef8 /]# gcloud info - # Your selected project info should be displayed here - ``` - -### Setup Google Analytics superProxy - -1. Clone the **Google Analytics superProxy** project on Github: to your local. - -2. Remove the first 2 lines in the [`src/app.yaml`{: .filepath}](https://github.com/googleanalytics/google-analytics-super-proxy/blob/master/src/app.yaml#L1-L2) file: - - ```diff - - application: your-project-id - - version: 1 - ``` - -3. In `src/config.py`{: .filepath}, add the `OAUTH_CLIENT_ID` and `OAUTH_CLIENT_SECRET` that you gathered from your App Engine Dashboard. - -4. Enter any random key for `XSRF_KEY`, your `config.py`{: .filepath} should look similar to this - - ```python - #!/usr/bin/python2.7 - - __author__ = 'pete.frisella@gmail.com (Pete Frisella)' - - # OAuth 2.0 Client Settings - AUTH_CONFIG = { - 'OAUTH_CLIENT_ID': 'YOUR_CLIENT_ID', - 'OAUTH_CLIENT_SECRET': 'YOUR_CLIENT_SECRET', - 'OAUTH_REDIRECT_URI': '%s%s' % ( - 'https://chirpy-test-XXXXXX.ue.r.appspot.com', - '/admin/auth' - ) - } - - # XSRF Settings - XSRF_KEY = 'OnceUponATimeThereLivedALegend' - ``` - {: file="src/config.py"} - - > You can configure a custom domain instead of `https://PROJECT_ID.REGION_ID.r.appspot.com`. - > But, for the sake of keeping it simple, we will be using the Google provided default URL. - {: .prompt-info } - -5. From inside the `src/`{: .filepath} directory, deploy the app - - ```console - [root@bc96abf71ef8 src]# gcloud app deploy - Services to deploy: - - descriptor: [/tmp/google-analytics-super-proxy/src/app.yaml] - source: [/tmp/google-analytics-super-proxy/src] - target project: [chirpy-test-XXXX] - target service: [default] - target version: [VESRION_NUM] - target url: [https://chirpy-test-XXXX.ue.r.appspot.com] - - - Do you want to continue (Y/n)? Y - - Beginning deployment of service [default]... - ╔════════════════════════════════════════════════════════════╗ - ╠═ Uploading 1 file to Google Cloud Storage ═╣ - ╚════════════════════════════════════════════════════════════╝ - File upload done. - Updating service [default]...done. - Setting traffic split for service [default]...done. - Deployed service [default] to [https://chirpy-test-XXXX.ue.r.appspot.com] - - You can stream logs from the command line by running: - $ gcloud app logs tail -s default - - To view your application in the web browser run: - $ gcloud app browse - ``` - -6. Visit the deployed service. Add a `/admin` to the end of the URL. - -7. Click on **Authorize Users** and make sure to add yourself as a managed user. - -8. If you get any errors, please Google it. The errors are self-explanatory and should be easy to fix. - -If everything went good, you'll get this screen: - -![superProxy-deployed](/posts/20210103/03-superProxy-deployed.png){: width="1366" height="354"} - -### Create Google Analytics Query - -Head to `https://PROJECT_ID.REGION_ID.r.appspot.com/admin` and create a query after verifying the account. **GA Core Reporting API** query request can be created in [Query Explorer](https://ga-dev-tools.appspot.com/query-explorer/). - -The query parameters are as follows: - -- **start-date**: fill in the first day of blog posting -- **end-date**: fill in `today` (this is a parameter supported by GA Report, which means that it will always end according to the current query date) -- **metrics**: select `ga:pageviews` -- **dimensions**: select `ga:pagePath` - -In order to reduce the returned results and reduce the network bandwidth, we add custom filtering rules [^ga-filters]: - -- **filters**: fill in `ga:pagePath=~^/posts/.*/$;ga:pagePath!@=`. - - Among them, `;` means using _logical AND_ to concatenate two rules. - - If the `site.baseurl` is specified, change the first filtering rule to `ga:pagePath=~^/BASE_URL/posts/.*/$`, where `BASE_URL` is the value of `site.baseurl`. - -After Run Query, copy the generated contents of **API Query URI** at the bottom of the page and fill in the **Encoded URI for the query** of SuperProxy on GAE. - -After the query is saved on GAE, a **Public Endpoint** (public access address) will be generated, and we will get the query result in JSON format when accessing it. Finally, click Enable Endpoint in **Public Request Endpoint** to make the query effective, and click Start Scheduling in **Scheduling** to start the scheduled task. - -![superproxy-query](/posts/20210103/04-superproxy-query.png){: width="1100" height="126"} - -## Configure Chirpy to Display Page View - -Once all the hard part is done, it is very easy to enable the Page View on Chirpy theme. Your superProxy dashboard should look something like below and you can grab the required values. - -![superproxy-dashboard](/posts/20210103/05-superproxy-dashboard.png){: width="1210" height="694"} - -Update the `_config.yml`{: .filepath} file of [**Chirpy**][chirpy-homepage] project with the values from your dashboard, to look similar to the following: - -```yaml -google_analytics: - id: 'G-V6XXXXXXX' # fill in your Google Analytics ID - pv: - proxy_endpoint: 'https://PROJECT_ID.REGION_ID.r.appspot.com/query?id=' - cache_path: # the local PV cache data, friendly to visitors from GFW region -``` -{: file="_config.yml"} - -Now, you should see the Page View enabled on your blog. - -## Reference - -[^ga-filters]: [Google Analytics Core Reporting API: Filters](https://developers.google.com/analytics/devguides/reporting/core/v3/reference#filters) - -[chirpy-homepage]: https://github.com/cotes2020/jekyll-theme-chirpy/ diff --git a/_sass/addon/commons.scss b/_sass/addon/commons.scss index 5e865de..faf0508 100644 --- a/_sass/addon/commons.scss +++ b/_sass/addon/commons.scss @@ -388,10 +388,6 @@ i { } } -.pageviews .fa-spinner { - font-size: 80%; -} - .post-meta { font-size: 0.85rem; diff --git a/assets/js/data/swcache.js b/assets/js/data/swcache.js index 14a9f56..9ff3899 100644 --- a/assets/js/data/swcache.js +++ b/assets/js/data/swcache.js @@ -47,8 +47,4 @@ const allowedDomains = [ ]; /* Requests that include the following path will be banned */ -const denyUrls = [ - {% if site.google_analytics.pv.cache_path %} - '{{ site.google_analytics.pv.cache_path | absolute_url }}' - {% endif %} -]; +const denyUrls = []; diff --git a/assets/lib b/assets/lib index 5f28c7d..557de30 160000 --- a/assets/lib +++ b/assets/lib @@ -1 +1 @@ -Subproject commit 5f28c7d5107a1c2e30381765194269680a3d0eae +Subproject commit 557de301fe393fb4660a338ae3c1b72ec2b3bf7c