用 Google Sheet + Google App Script 打造網頁計數器

過去本站無論是全站瀏覽數或是單篇文章的瀏覽數,都是透過 Google Analytics 搭配 Google Sheets 串接提供的,主要是參考前輩 August 大大的文章更改而成,但上述的方法將會在明年 7 月遇到問題—— Google Analytics 將從通用版全面改為 Google Analytics 4(GA4)。

然而目前 GA4 尚未提供與 Google Sheets 搭配串接的官方外掛(非官方大多須付費),因此筆者便將腦筋動到了 Google 的另一項服務—— Google Apps Script(GAS)上,本文將紀錄筆者如何透過 Google Sheets + Google Forms 紀錄本站瀏覽數,並透過 Google Apps Script 串接將瀏覽數顯示在網站上。

整體流程如何運作?

運作流程圖

運作流程圖

首先,我們會先透過 Google Forms 功能,在所有使用者到訪網站時觸發並記錄下來,將結果回傳到與表單連動的 Google Sheets 中。

接下來,在 Google Sheets 中我們將進行簡單的數據整理,以利後續網頁接收資料時使用,在這裡,便是將 Google Sheets 作為一個小型資料庫使用。

最後,我們透過 Google Apps Script 將 Google Sheets 中的資料變身成為 API,並在網站上串接使用,顯示於網頁前端。

就讓我們開始吧!

先建立紀錄用的 Google 表單

在這個表單中,我們要紀錄的是使用者進入的網址,並增加計數,紀錄網只是為了後續可以在個別文章頁面上顯示個別瀏覽數,而計數欄位則是方便後續直接加總。

需要注意的是,這兩個欄位在 Google Forms 上的設定,必須選擇「簡答」,且不可設為必填(參考下圖),這是避免後續傳送資料發生錯誤。

表單題目設定完成後,點選上方「回覆」分頁,並點選「建立試算表」,後續我們會將這個試算表作為小型資料庫來使用。

將網頁計數透過 Google Form 寫入 Google Sheet 吧

接下來我們回到網站,要來寫 Code 將資料傳入 Google Sheets 中,這部份將會參考同樣是 August 大大的文章來進行。

事實上,這個方法是透過 Google Forms 回傳到後端的端口作為我們要將資料傳入 Google Sheets 的入口,因此必須取得這份表單的:

  1. POST 的 URL
  2. 各欄位的 name

先來取得 POST 的 URL 吧

取得的方式也很簡單,前往稍早建立完成的表單頁面後(可以點擊右上方的預覽前往),點擊右鍵 → 檢查,即可開啟 DevTools 界面。

在此界面中點選右上方「…」符號並選取搜尋,或按下快捷鍵「crtl+F / cmd+F」,並在搜尋欄位中搜尋「<form」。

在這段程式碼中,會有一個「action=」開頭,後方接著一段網址,將這段網址複製並記錄下來,後面會使用它。

本次所取得的網址如下(本網址為 Demo 用,非實際本站用網址):

https://docs.google.com/forms/u/0/d/e/1FAIpQLScBtEkMNxQJrrIK0kLJHMOUFnPqWv7Dpa7P36J7BLrGszqJuQ/formResponse

接下來取得各欄位的 name

繼續在網頁右側的 DevTools 中搜尋「entry.」,會看到幾列 <input type=“hidden” 開頭的程式碼,由上而下會對應到你所建立的表單欄位(依照建立順序而不是顯示順序)。

在程式碼中的「name=」後方內容,就是我們所需要的 name 值,本文範例如下:

entry.1515159479
entry.790304345

取得這些資訊後,就可以回到網站,準備讓資料記入 Google Sheets 囉!

回到網站準備寫 Code

在這裡,我們需要取得目前網頁的網址,為了方便後續使用,這邊只需要取得網址路徑(Pathname)的部份,可以透過 「location.pathname」來取得。

let pageviewUrl = location.pathname;  
// 假設網址為 https://example.com/abc/  
// pageviewUrl 為 /abc/  

而計數的部份則固定為 1:

let pageviewCount = 1;

接下來要將資料透過 $ajax POST 到 Google Forms 上(記得要先引入 jQuery):

let data = {  
    'entry.1515159479': pageviewUrl,  
    'entry.790304345': pageviewCount  
};  
$.ajax({  
    type: 'POST',  
    url: 'https://docs.google.com/forms/d/e/1FAIpQLSeTgHEpVpuV_OHakO-25X-O7I4T1tIzIAUqHWLRvUqG9e6TvQ/formResponse',  
    data: data,  
    contentType: 'application/json',  
    dataType: 'jsonp'  
});

其中,data 裡的 key 就是稍早在 Google Forms 中取得 entry. 開頭的 name,而 url 則是 Google Forms 中取得的 url。

完成後到瀏覽器嘗試載入網頁,應該就可以發現 Google Sheets 中出現此筆資料了。

將 Google Sheets 作為資料庫使用

接著回到 Google Sheets,我們要透過 Google Apps Script 將資料傳輸給網頁使用,但在使用前你會發現 Google Sheets 中的資料是分開一筆一筆紀錄的,但我們在實際使用上會希望是呈現不同頁面累積的流量,因此需要先在 Google Sheets 中進行基本處理。

透過 QUERY 函式快速整理資料

首先,先在 Google Sheets 中建立一個新分頁,我們將他命名為「Pageview」。

接著,這邊將會使用到 Google Sheets 的一個函式「QUERY」,這是一個可以在 Google Sheet 中方便使用 SQL 資料庫語法的函式,在進行較複雜的資料整理時相當有用,而 QUERY 的函式使用方式可參考官方說明

QUERY 函式用法:

=QUERY(資料範圍,SQL 語法,標題[選填])

而在這次的資料中,我們需要的是表單回應裡的網址與計數兩欄,其中計數欄會希望是加總後的結果,因此在 Pageview 分頁中的 A1 儲存格中輸入如下公式:

=QUERY('表單回應 1'!B:C,"select B,sum(C) group by B order by sum(C) desc")

在 SQL 語法部份,Google Sheets 的 QUERY 函式不像一般 SQL 可以使用表頭來選取資料,而是要使用絕對位置的欄位來選取,各內容說明如下:

  • select B, sum(C):指將 B 欄與加總後的 C 欄選取出來。
  • group by B:因為有使用 sum 函式,必須透過 group by 來告訴系統資料的分組方式,這邊選擇 B 欄也就是網址來進行分組。
  • order by sum(C) desc:以 sum(C) 的結果遞減排序。

資料進行處理後你將會得到如下的表單:

用 Google Apps Script 取得 Google Sheets 的資料

Google Apps Script 是由 Google 開發的腳本平台(Scripting Platform),支援使用 JavaScript 撰寫程式碼,除了可以串連 Google 文件、試算表等工具外,妥善使用甚至能作為輕量後端。

而 Google Apps Script 免費的額度是一天 2 萬次,因此對於小流量的網站基本上是相當足夠的。

前往 Google Apps Script 撰寫程式碼

要前往 Google Apps Script,可以在 Google Sheets 上方選單選取「擴充功能」→ 「Apps Script」。

開啟 Google Apps Script 後,就可以開始進行程式碼的撰寫了。

獲取 Google Sheets 資料

首先,要先讓 Google Apps Script 能讀取 Google Sheets 的資料,透過以下公式可以取得資料,並將資料轉為陣列形式。

var ss = SpreadsheetApp.getActiveSpreadsheet();  // 設定要取得資料的文件  
var sheet = ss.getSheetByName("Pageview");       //要取得資料的分頁名稱  
var range = sheet.getRange("A:B");               // 設定資料範圍  
var data = range.getValues();                    // 取得資料陣列

在這裡我們可以在預設的 myFunction() 中,透過 console.log(); 的方式看一下獲取的資料內容,程式碼如下:

function myFunction() {  
    console.log(data);  
}

點選畫面上方的「執行」,首次將會跳出授權畫面,點選「審查授權」。

點選後會跳出警示畫面,因為這個應用程式是我們自己寫的,因此可以放心按下下方的「前往」,並選擇要授權的 Google 帳號(目前登入使用的)。

取得授權後,下方執行記錄就會列出我們所選取的資料陣列內容。

將資料以 Json 形式提供給網站

Google Apps Script 取得 Google Sheets 的資料後,我們要再將資料轉成 Json 形式,讓網站能順利讀取。

而 Google Apps Script 的資料要能夠對外發送,必須透過一個特別的函式 doGet() 來進行:

function doGet() {  
    var dataExportFormat = JSON.stringify(data); // 將資料陣列轉換成為 Json 格式  
    return ContentService.createTextOutput(dataExportFormat).setMimeType(ContentService.MimeType.JSON); // 回傳資料  
}

完成後,點選畫面上方的「部署」→「新增部署作業」。

點選左方齒輪 →「網頁應用程式」。

下方的「誰可以存取」改選「任何人」,並點擊「部署」。

完成部署後會獲得一串網址:

https://script.google.com/macros/s/xxxxxxxxxxxxxxxxxxx/exec

後續將會在網站上透過此網址來串接網頁瀏覽數。

最後一哩路:用 Javascript 將資料放入頁面中

回到網頁,同樣使用 jQuery 的 $ajax 來串接資料,其中的 url 填入前面從 Google Apps Script 所取得的連結,程式碼如下:

$.ajax({
    url: 'https://script.google.com/macros/s/AKfycbypNr2QBNkSkJ6FBaYz8C8o2E8IuWsB4AzL-UltX7aUeBZJ-d00uGaMm7Joy-gP2nT_Bw/exec',
    type: 'get',
    async: false,
    success: function (res) {
        // 獲取資料成功
    },
    error: function (res) {
        // 獲取資料失敗
    }
});

成功獲取資料後,理想中我們希望依據不同網址獲取不同瀏覽次數,因此使用一個 for 迴圈來篩選出資料:

for (var i of res) {
    if (i[0] === pageviewUrl) { // 當 i[0] 也就是陣列中的網址 等於 本頁路徑時
        var pv = i[1]; // 讓 pv 等於 i[1] 也就是陣列中的計數
        $('#pv').text(pv); // 將 #pv 元素加入此數值
    }
}

最後整合 for 迴圈與 $ajax 如下:

$.ajax({
    url: 'https://script.google.com/macros/s/AKfycbypNr2QBNkSkJ6FBaYz8C8o2E8IuWsB4AzL-UltX7aUeBZJ-d00uGaMm7Joy-gP2nT_Bw/exec',
    type: 'get',
    async: false,
    success: function (res) {
        for (var i of res) {
            if (i[0] === pageviewUrl) { // 當 i[0] 也就是陣列中的網址 等於 本頁路徑時
                var pv = i[1]; // 讓 pv 等於 i[1] 也就是陣列中的計數
                $('#pv').text(pv); // 將 #pv 元素加入此數值
            }
        }
    },
    error: function (res) {
        console.log('Error')
    }
});

到這裡就完成囉!

最後,Demo 頁面與程式碼範例都放在 GitHub 上,也歡迎大家提供其他建議囉!

coffee

請我喝杯咖啡,讓我有持續創作的動力吧!