使用 Google Apps Script 串接 Google Analytics API,整合多站數據
Let's Write

Let's Write @letswrite

About: 前端工程師 August 的學習筆記 — solving problems, in simple ways.

Location:
Taiwan, Taipei
Joined:
Jun 18, 2022

使用 Google Apps Script 串接 Google Analytics API,整合多站數據

Publish Date: Mar 29
1 0

本篇要解決的問題

一間公司裡可能旗下會有多個網站,想同時查看所有網站的 GA 數據,通常需要開啟多個瀏覽器視窗並排顯示,操作較為繁瑣。

如果可以改由 API 來取得 GA 的數據,工程師就可以把各站的資料顯示在一個頁面上,而不用同時開多個 GA 來看。


開通 GA API

取得 GCP 專案編號

要先有 Google Cloud Platform(GCP)的專案,沒有的話登入自己的 Google 帳號,就可以先增一個。

專案編號就在 資訊主頁 上:

GCP 主控台首頁,顯示專案編號位置

開通 GA API 功能

在使用 API 前,必須先於 GCP 開通對應的功能。

GCP 的專案點擊選單中的「API 和服務」> 「程式庫」:

GCP 中 API 與服務 > 程式庫選單頁面

搜尋框上搜尋「google analytics data api」,會看到結果清單裡會出現「Google Analytics Data API」,點進去後,再點擊啟用,就完成了:

在程式庫搜尋 Google Analytics Data API

點擊啟用 Google Analytics Data API


取得 GA 的資源 ID

看要抓的是哪一個 GA 的資料,進到 GA 後台,進到「管理」,點擊「資源詳細資料」:

GA 後台管理介面

接著右上角就會看到資源編號:

GA 資源詳細頁面,顯示資源 ID


調用 GA API 程式碼部份

因為調用 Google 的 API,要先經過認證的程序,但如果是寫在跟 GA 相同帳號的 Google Apps Script,就可以省掉這一段。

Google Apps Script 上新增專案

Google Apps Script 的頁面上,新增一個專案:

Google Apps Script 新增專案畫面

接著可以直接複製貼上以下的程式碼。

瀏覽量、活躍人數

以下程式碼是抓瀏覽量、活躍人數的:

var propertyId = "xxxxxx";  // 替換成 GA 的資源編號
var startDate = "2025-01-01", // 替換成想要從哪一天開始抓的日期

function getGA4Data() {

  var apiUrl = `https://analyticsdata.googleapis.com/v1beta/properties/${propertyId}:runReport`;

  var payload = {
    "dateRanges": [{
      "startDate": startDate,
      "endDate": "today"
    }],
    "metrics": [
      { "name": "screenPageViews" }, // 瀏覽數
      { "name": "activeUsers" } // 活躍用戶數
    ]
  };

  var options = {
    "method": "post",
    "contentType": "application/json",
    "headers": {
      "Authorization": "Bearer " + ScriptApp.getOAuthToken()
    },
    "muteHttpExceptions": true,
    "payload": JSON.stringify(payload)
  };

  var response = UrlFetchApp.fetch(apiUrl, options);
  var data = JSON.parse(response.getContentText());

  // 檢查回應中是否有 rows 資料
  if (data.rows && data.rows.length > 0) {

    // 取得瀏覽數和活躍用戶數
    var screenPageViews = data.rows[0].metricValues[0].value;
    var activeUsers = data.rows[0].metricValues[1].value;

    // 回傳資料
    return {
      "totalPageViews": screenPageViews,
      "activeUsers": activeUsers
    };

  } else {
    // 若無符合資料,則回傳 0 作為預設值
    return {
      "totalPageViews": 0,
      "activeUsers": 0
    };
  }
}
Enter fullscreen mode Exit fullscreen mode

瀏覽量、活躍人數:指定頁面標題

除了抓全站的資料,可以抓指定網頁的 title 是什麼結尾,比如這邊抓的是「會員中心」為結尾的頁面:

var propertyId = "xxxxxx";  // 替換成 GA 的資源編號
var startDate = "2025-01-01", // 替換成想要從哪一天開始抓的日期
var pageTitle = "會員中心"; // 替換成想要篩選的頁面標題文字

function getGA4DataPage() {

  var apiUrl = `https://analyticsdata.googleapis.com/v1beta/properties/${propertyId}:runReport`;

  var payload = {
    "dateRanges": [{
      "startDate": startDate,
      "endDate": "today"
    }],
    "metrics": [
      { "name": "screenPageViews" }, // 瀏覽數
      { "name": "activeUsers" } // 活躍用戶數
    ],
    "dimensionFilter": {
      "filter": {
        "fieldName": "unifiedScreenName",
        "stringFilter": {
          "value": pageTitle,
          "matchType": "ENDS_WITH"
        }
      }
    }
  };

  var options = {
    "method": "post",
    "contentType": "application/json",
    "headers": {
      "Authorization": "Bearer " + ScriptApp.getOAuthToken()
    },
    "muteHttpExceptions": true,
    "payload": JSON.stringify(payload)
  };

  var response = UrlFetchApp.fetch(apiUrl, options);
  var data = JSON.parse(response.getContentText());

  if (data.rows && data.rows.length > 0) {
    var screenPageViews = data.rows[0].metricValues[0].value;
    var activeUsers = data.rows[0].metricValues[1].value;
    return {
      "totalPageViews": screenPageViews,
      "activeUsers": activeUsers
    };
  } else {
    return {
      "totalPageViews": 0,
      "activeUsers": 0
    };
  }
}
Enter fullscreen mode Exit fullscreen mode

即時人數

var propertyId = "xxxxxx";  // 替換成 GA 的資源編號

function getGA4RealtimeData() {

  var apiUrl = `https://analyticsdata.googleapis.com/v1beta/properties/${propertyId}:runRealtimeReport`;

  var payload = {
    "metrics": [{
      "name": "activeUsers"
    }]
  };

  var options = {
    "method": "post",
    "contentType": "application/json",
    "headers": {
      "Authorization": "Bearer " + ScriptApp.getOAuthToken()
    },
    "muteHttpExceptions": true,
    "payload": JSON.stringify(payload)
  };

  var response = UrlFetchApp.fetch(apiUrl, options);
  var data = JSON.parse(response.getContentText());

  // 取得即時人數
  return data.rows[0].metricValues[0].value;
}
Enter fullscreen mode Exit fullscreen mode

即時人數:指定頁面標題

這邊一樣是抓「會員中心」為結尾的頁面:

var propertyId = "xxxxxx";  // 替換成 GA 的資源編號
var pageTitle = "會員中心"; // 替換成想要篩選的頁面標題文字

function getGA4RealtimeDataPage() {
  var apiUrl = `https://analyticsdata.googleapis.com/v1beta/properties/${propertyId}:runRealtimeReport`;

  // 在 payload 中新增 dimensions 和 dimensionFilter
  var payload = {
    "metrics": [{
      "name": "activeUsers"
    }],
    "dimensions": [{
      "name": "unifiedScreenName"
    }],
    "dimensionFilter": {
      "filter": {
        "fieldName": "unifiedScreenName",
        "stringFilter": {
          "value": pageTitle,
          "matchType": "ENDS_WITH"
        }
      }
    }
  };

  var options = {
    "method": "post",
    "contentType": "application/json",
    "headers": {
      "Authorization": "Bearer " + ScriptApp.getOAuthToken()
    },
    "muteHttpExceptions": true,
    "payload": JSON.stringify(payload)
  };

  var response = UrlFetchApp.fetch(apiUrl, options);
  var data = JSON.parse(response.getContentText());

  var totalActiveUsers = 0;

  // 累加所有匹配頁面的人數
  if (data.rows && data.rows.length > 0) {
    data.rows.forEach(function (row) {
      totalActiveUsers += parseInt(row.metricValues[0].value, 10);
    });
  }

  return totalActiveUsers.toString(); // 返回所有匹配頁面的總人數
}
Enter fullscreen mode Exit fullscreen mode

以 POST 的參數,判斷要給哪種資料

上面一共寫了四個函式,我們需要一個參數,讓 API 知道要回應的是哪個資料。

這邊用的參數是 typetype 不同值,就給不同資料,共有 4 個值可以寫:

  • data:瀏覽量、活躍人數。
  • dataPage:瀏覽量、活躍人數:指定頁面標題。
  • realtimeData:即時人數。
  • realtimeDataPage:即時人數:指定頁面標題。
// 回應錯誤訊息
function createErrorResponse(message, code) {
  var errorResponse = {
    success: false,
    error: message,
    code: code || 400,
    timestamp: new Date().toISOString()
  };
  var jsonOutput = ContentService.createTextOutput(JSON.stringify(errorResponse));
  jsonOutput.setMimeType(ContentService.MimeType.JSON);
  return jsonOutput;
}

// 處理 POST
function doPost(e) {
  // 確認有傳入內容
  if (!e.postData || !e.postData.contents) {
    return createErrorResponse("無效請求:未收到 POST 資料。" + e.postData);
  }

  // 將 POST 資料解析成 JSON
  var requestData;
  try {
    requestData = JSON.parse(e.postData.contents);
  } catch (error) {
    return createErrorResponse("JSON 格式無效。");
  }

  // 檢查是否有 type 參數
  if (!requestData.type) {
    return createErrorResponse("缺少「type」參數。");
  }

  var output;

  // 根據 type 參數執行不同的邏輯
  switch (requestData.type) {
    // 瀏覽量、活躍人數
    case "data":
      var reportData = getGA4Data();
      output = {
        "totalPageViews": reportData.totalPageViews,
        "activeUsers": reportData.activeUsers
      };
      break;
    // 瀏覽量、活躍人數:指定頁面標題
    case "dataPage":
      var reportData = getGA4DataPage();
      output = {
        "totalPageViews": reportData.totalPageViews,
        "activeUsers": reportData.activeUsers
      };
      break;
    // 即時人數
    case "realtimeData":
      var reportData = getGA4RealtimeData();
      output = {
        "activeUsers": reportData
      };
      break;
    // 即時人數:指定頁面標題
    case "realtimeDataPage":
      var reportData = getGA4RealtimeDataPage();
      output = {
        "activeUsers": reportData
      };
      break;
    default:
      return createErrorResponse("type 錯誤");
  }

  // 回傳 JSON 格式的結果
  var jsonOutput = ContentService.createTextOutput(JSON.stringify(output));
  jsonOutput.setMimeType(ContentService.MimeType.JSON);
  return jsonOutput;
}
Enter fullscreen mode Exit fullscreen mode

Google Apps Script 連結到 GCP 專案

左側選單點擊「設定」,接著頁面往下滑,有一項「 Google Cloud Platform (GCP) 專案」,點擊這項的「變更專案」:

GAS 設定頁面,點擊變更 GCP 專案

接著輸入框就填上第一步在 GCP 上取得的編號,再點擊「設定專案」就可以了:

填入 GCP 專案編號並點選設定

如果專案存在,連結就會成功,成功的畫面像這樣:

顯示成功連結到 GCP 專案的畫面

設定完後,這份 GAS 檔就可以使用 GCP 上開啟的 GA API。


部署 GAS

Google Apps Script 的程式如果要能對外,要部署出去才行。

點擊右上角的「部署」> 「管理部署作業」:

GAS 部署選單,點選管理部署作業

部署的類型是「網頁應用程式」:

選擇部署類型為網頁應用程式

「誰可以存取」要選擇「所有人」:

設定所有人皆可存取 API

選好後,點擊「部署」,需要授權時就直接授權。

部署成功,就會取得一個網址,這個網址就是對外的 API 網址了:

部署成功後顯示 API 網址

最後,只要 POST 到這個網址,帶上指定的參數 type,就可以取得我們想要的資料。


手動補權限

如果 POST 後,取到的資料一直是 0,代表部署時提供的權限不完整,就要手動補授權。

點擊左側的「專案設定」,在編輯器中顯示「appsscript.json」資訊清單檔案 打勾:

GAS 設定中勾選顯示 JSON 設定檔

接著回到編輯器,會看到 appsscript.json 這個檔案,補上以下:

"oauthScopes": [
    "https://www.googleapis.com/auth/script.external_request",
    "https://www.googleapis.com/auth/analytics.readonly"
]
Enter fullscreen mode Exit fullscreen mode

appsscript.json 中新增 oauthScopes 權限設定

最後再次部署,會出現要補權限的授權,一律給過就行,就可以取得 GA 上的資料了。


完整程式碼

完整的 Google Apps Script 程式碼如下,可以直接複製貼上:

Comments 0 total

    Add comment