前言
博客各个页面的 Page View (PV) 统计算是我一直都挺想要的一个功能了,但是现有的解决方案都有点缺点:
不蒜子:这个是我一开始考虑的,但是问题是导入已有的数据有点麻烦而且有点担心跑路
LeanCloud:很多地方都推荐这个,但是它的 API 对加载速度影响大而且流程麻烦。
我需要的是一个尽量不影响加载速度,同时数据不易失而且最好避免导入旧数据的方案,思来想去只有从 Google Analytics 获取数据满足需求了,这时候我也发现了hexo-related-popular-posts ,但是问题是点击量只是这个 repo 的附属功能,我并不想要相关主题的功能,然后点开 Document 一看全是日语也不方便二次开发,所以决定自己实现。
本文就是简单介绍如何手动实现用 Google Analytics API 为博客加上阅读量统计。
环境准备
hexo 毕竟是一个静态博客,如果想添加阅读量统计不可避免的要引入一个后端,由于我的博客正在使用的评论系统 hashover 是基于 php 的,所以我第一想法就是用 php 来完成这个功能。
php
所以如果你想按照本文的过程来为你的博客加上阅读量,应该先配置一个 php 环境,以 apt 为例
1 apt install php php-fpm composer -y
nginx
然后修改服务器相关配置,这里以 Nginx 为例
1 2 3 4 5 location ~* \.php$ { include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass unix:/run/php/php7.0-fpm.sock; }
之后可以用 phpinfo 来测试下是否配置成功,更多的就不再赘述了。
获取 Google Analytics 相关信息
这里偷懒使用了 v3 的 API,但是由于功能简单其实迁移到 v4 非常容易。
服务账号
根据 Google Analytics 的说法,我们首先需要一个服务账号,创建的过程非常简单,只要按照他说的步骤一步一步来就行了,比如我的是这样的。
要注意的是创建完后会提示你下载 key,这个要保留好,后面会用到。
Google PHP Apiclient
然后我们需要配置依赖,这里可以选择直接下载源码解压或者使用 composer,由于懒得用 scp 传文件我选择用 composer。
1 2 composer require google/apiclient:^2.0 composer install --no-dev
数据视图id
为了获取数据,我们还需要获取 Google Analytics 数据视图的 id。
由于我们希望拿到的是全部阅读量,因此不用任何过滤,直接用整站数据视图即可。
点击数据视图设置就能看到 id 了。
简单的请求转发
由于我们的后端并不需要很复杂的功能,只要简单的按照页面标题获取点击量就可以了,所以这里我直接按照官方的例子改了下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 <?php header ('Content-type: application/json' );require_once __DIR__ . '/vendor/autoload.php' ;function initializeAnalytics ( ) { $KEY_FILE_LOCATION = '/path/to/your/key.json' ; $client = new Google_Client (); $client ->setApplicationName ("Hello Analytics Reporting" ); $client ->setAuthConfig ($KEY_FILE_LOCATION ); $client ->setScopes (['https://www.googleapis.com/auth/analytics.readonly' ]); $analytics = new Google_Service_Analytics ($client ); return $analytics ; } function getResults ($analytics , $profileId , $title ) { return $analytics ->data_ga->get ( 'ga:' . $profileId , '2017-01-01' , // 这个时间足够久远即可 date ('Y-m-d' ), // 当天日期 'ga:pageviews' , // 页面PV ['dimensions' => 'ga:pageTitle' , // 按照标题划分 'filters' => 'ga:pageTitle==' .$title , // 按照标题过滤 'samplingLevel' => 'HIGHER_PRECISION' ]); } try { $clicks = 0 ; if (!isset ($_GET ['title' ])){ $clicks = "(╯‵□′)╯︵┴─┴" ; } else { $analytics = initializeAnalytics (); $results = getResults ($analytics , YOUR_PROFILE_ID, rawurlencode (htmlspecialchars_decode ($_GET ['title' ]))); $rows = $results ->getRows (); switch (count ($rows )) { case 0 : $clicks = 0 ; break ; case 1 : $clicks = $rows [0 ][1 ]; break ; default : $clicks = "(╯‵□′)╯︵┴─┴" ; break ; } } echo json_encode (['clicks' => $clicks ]); exit (0 ); } catch (Exception $e ){ echo json_encode (["clicks" => "(╯‵□′)╯︵┴─┴" ]); exit (0 ); }
注意这里要填入之前下载 key 的路径和你自己数据视图的 id。
然后现在只要在 GET 请求中带上标题就可以获取到阅读量了,比如对于我的博客访问这里 就可以获取主页的点击量。
当然如果你发现了什么注入漏洞也欢迎告诉我...
前端
完成了后端后接下来需要的就是前端展示了。
以下都是建立在 NexT 主题的基础上,如果你使用其他的主题道理也是类似的。
发送请求
由于 NexT 中使用了 jQuery 因此前端代码编写就很简单了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 var title = document .querySelector ('title' ).innerHTML ;var setClicks = function (data ){ var spans = document .querySelectorAll ('#clicks' ); var clicks = "(╯‵□′)╯︵┴─┴" ; if (data.hasOwnProperty ('clicks' )) clicks = data['clicks' ]; for (var i=0 ;i<spans.length ;i++) spans[i].innerHTML = clicks; } $.ajax ({ 'url' : '/clicks/clicks.php' , 'data' : { 'title' : title }, 'dataType' : 'json' , 'method' : 'GET' , 'success' : setClicks, 'error' : setClicks });
把这个文件放到 next 主题的 source/js
下,但是这时候访问的话这个 js 还不会被加载。
接着修改 layout/_layout.swig
在最后引入我们的 js 文件。
1 2 3 4 5 6 7 8 9 10 11 ... ... ... {% include '_third-party/pangu.swig' %} {% include '_third-party/scroll-cookie.swig' %} {% include '_third-party/exturl.swig' %} {% include '_third-party/bookmark.swig' %} <script type="text/javascript" src="{{ url_for(theme.js) }}/src/clicks.js"></script> </body> </html>
现在只要页面中 id 为 clicks 的 span 的内容都会被延迟加载为阅读量了。
展示数据
接下来就是要在哪里展示阅读量了。
由于我是前端废,所以干脆就用原来主题的 CSS 并且尽量不破坏原主题的一体性,所以我选择的时候在文章下方发表时间和分类之间加上阅读量,同时在每页的页脚添加访问量展示,因此需要分别修改 layout/_partials/footer.swig
和 layout/_marcro/post.swig
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... ... ... {% if theme.footer.powered %} <div class="powered-by">{# #}{{ __('footer.powered', '<a class="theme-link" target="_blank"' + nofollow + ' href="https://hexo.io">Hexo</a>') }}{# #}</div> {% endif %} <div class="powered-by"> <span class="post-meta-divider">|</span> 当前页面阅读量 <span id='clicks'>>_<</span> </div> {% if theme.footer.powered and theme.footer.theme.enable %} <span class="post-meta-divider">|</span> {% endif %} ... ... ...
post.swig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ... ... ... </span> {% if not is_index %} <i class="fa fa-mouse-pointer" aria-hidden="true"></i> <span class="post-meta-divider">|</span> <span class="post-meta-item-text">阅读量:</span> <span id = "clicks">>_<</span> {% endif %} {% if post.categories and post.categories.length and theme.post_meta.categories %} ... ... ...
到此就大功告成了,现在打开博客就可以看到每个页面的阅读量了。
后记
到这里反而有点怀念以前的 WordPress 了,省心的多。
不过既然是为了安全和简洁选择了 hexo,那就还是得有折腾的精神呀。
以后最好能在主页的每篇文章上加上阅读量,有时间再做吧(挖坑)。
参考资料
Google Analytics(分析)API 入门:适用于服务帐号的 PHP 快速入门