Google Analytics for Firebase กับ Offline Event ด้วย Measurement Protocol

เรื่องมันมีอยู่ว่า ในกรณีที่เรามี Frontend ที่เชื่อมต่อกับ Google Analytics แล้ว สามารถส่งข้อมูลต่าง ๆ ผ่านตัว Firebase SDK ได้อยู่แล้ว แล้วทางฝั่ง Backend ล่ะ ตัว Firebase Admin SDK มันไม่ได้มีตัว Analytic มาด้วย เราจะส่งข้อมูลได้อย่างไรบ้าง ?

Siwawes Wongcharoen
Firebase Thailand
4 min readJun 24, 2024

--

TLDR — Too long, Don’t Read;

แนวทางการส่ง Offline Event เข้าตัว Measurement Protocol ทำได้ดังนี้

  1. ฝั่ง Frontend ต้องเก็บ Client ID และ User ID มาให้ได้
  2. ฝั่ง Backend ใช้ Client ID และ User ID ที่ได้มาจาก Frontend ประกอบกัน แล้วส่งข้อมูลเข้าตัว Measurement Protocol เอง
Google Analytics for Firebase กับ Offline Event ด้วย Measurement Protocol

Google Analytics for Firebase ของดี ที่ใช้ง่าย แต่ดันมาไม่ครบ

เปิดหัวมาแบบนี้ แฟน ๆ Firebase อย่าพึ่งด่าผมนะ เพราะเรื่องมันมีอยู่ว่า ตั้งแต่สมัยที่ตัว Google Analytics for Firebase ออกมาใหม่ ๆ ตอนนั้นก็จะ Support อยู่แค่ Android กับ iOS จนผ่านมาพักใหญ่ ๆ ถึงจะ Support ฝั่ง Web แต่ว่าทั้งหมดนี้มันทำงานได้กับเฉพาะฝั่ง Frontend อย่างเดียว ไม่ครอบคลุมมาถึงฝั่ง Backend ด้วย

อ้าววว แล้วถ้าฝั่ง Backend ก็ต้องการส่งข้อมูลเข้า Analytics ด้วยล่ะ จะเอายังไง อันนี้ไม่ต้องห่วง เพราะว่า Google เองก็มีตัว Measurement Protocol ให้ใช้อยู่แล้ว เป็น REST API ธรรมดา ๆ เลย เพียงแค่ว่า ตัว Measurement Protocol มันจะไม่ได้รวมอยู่ใน SDK นะ ต้องเขียนเอง

แล้วทำไมฝั่ง Backend ต้องส่งข้อมูลเข้าฝั่ง Analyitcs ด้วยล่ะ ? ก็เพื่อเติมเต็มข้อมูลต่าง ๆ ที่ไม่สามารถทำได้จากฝั่ง Frontend ไง ยกตัวอย่าง เช่น ในแง่ของ ECommerce ปกติ Metric ส่วนใหญ่ สามารถวัดได้จาก Frontend อยู่แล้ว แต่จะมี Event บางอย่างที่ไม่สามารถวัดได้จาก Frontend ตรง ๆ นั่นก็คือ Metric ที่เกียวกับการจัดส่งบางตัว เนื่องจาก ข้อมูลที่เกียวกับการจัดส่ง มันจะไม่เกิดบน Frontend ของระบบเรา แต่ฝั่ง Backend เรามีข้อมูลพวกนี้อยู่แล้ว ฉะนั้น ถ้าเราอยากทำ Conversion ที่ครอบคลุมมาถึงเรื่องการจัดส่ง เราจะต้องให้ Backend เรา ส่ง Metric พวกนี้เข้ามาใน Analyitcs ด้วย

มาถึงตรงนี้ อาจจะมีคนหัวใส อยากจะเก็บ Stat บางอย่างบน Google Analytics เลยได้มั้ย คำตอบคือ ได้นะ ถ้า Stat พวกนั้นมันสามารถผูกกับข้อมูลที่มาจาก Frontend ได้ แต่ถ้าผูกไม่ได้ ก็ยังส่งเข้าไปได้ แต่ตัว Google Analytics จะไม่แสดงข้อมูลนั้น ข้อความนี้อาจจะงง ๆ หน่อย สรุป ๆ ง่าย ๆ ก็คือ เราไม่สามารถลักไก่ใช้งาน Google Analytics ในแบบผิด ๆ

ทำอย่างไร ?

เตรียมความพร้อม

  1. Firebase Account and Firebase Project
  2. Google Analytics Permissions

เริ่มกันที่ฝั่ง Frontend

ในตัวอย่างนี้จะเน้นมาทาง Web นะครับ

เริ่มจากให้เอา Analytics SDK ใส่ในเว็บให้เรียบร้อย (วิธีทำ)

จากนั้น จะมี 2 ส่วนสำคัญ ที่เราต้องทำ คือ

  1. Set User ID ให้ตัว Analytics SDK
  2. เอาค่า Google Analytics Client ID ออกมาจากตัว Analytics SDK
    อันนี้สำคัญที่สุด เพื่อให้ตัว Measurement Protocol ผูกข้อมูลได้อย่างถูกต้อง

1. Set User ID ให้ตัว Analytics SDK

ขั้นตอนนี้ถึงจะไม่จำเป็นต้องทำ แต่แนะนำให้ทำเป็นอย่างยิ่ง และหากเป็น User ID ที่ Backend ใช้งานด้วยก็จะดีที่สุด

import {
getAnalytics,
setUserId,
} from 'firebase/analytics'

export function analyticsSetUserId(userId: string) {
const analytics = getAnalytics()
setUserId(analytics, userId)
}

// https://firebase.google.com/docs/analytics/userid#web

รายละเอียดเต็ม ๆ แนะนำให้อ่านจากต้นทางนะครับ

2. เอาค่า Google Analytics Client ID ออกมาจากตัว Analytics SDK

อันนี้สำคัญที่สุด เพื่อให้ตัว Measurement Protocol ผูกข้อมูลได้อย่างถูกต้อง

import {
getAnalytics,
getGoogleAnalyticsClientId as getGoogleAnalyticsClientIdFirebase
} from 'firebase/analytics'

export function getGoogleAnalyticsClientId() {
const analytics = getAnalytics()
return getGoogleAnalyticsClientIdFirebase(analytics)
}

// https://firebase.google.com/docs/reference/js/analytics.md#getgoogleanalyticsclientid_b0a3b5a

อันนี้ ใน Doc ปกติจะไม่มีเขียนไว้ แต่มีในนี้

สำคัญมาก อย่าลืมเอาค่าที่ได้ ส่งไปเก็บที่ Backend ด้วยนะ

เอาละ ในฝั่ง Frontend เราเรียบร้อยแล้ว ง่ายนิดเดียว (ที่เหลือยากละ 😂)

มาต่อกันที่ฝั่ง Backend

ในตัวอย่างนี้จะเน้นเป็น Node.js แบบ TypeScript นะครับ

จะมี 3 ส่วนสำคัญ ที่เราต้องทำ คือ

  1. ทำให้ Backend เราส่งข้อมูลเข้า Measurement Protocol ได้
  2. เตรียมค่า API Secret และ Measurement ID
  3. เตรียมค่า User ID และ Google Analytics Client ID ที่ได้มาจาก Frontend

1. ทำให้ Backend เราส่งข้อมูลเข้า Measurement Protocol ได้

จะใช้ Axios หรือ Lib ตัวอื่น อันนี้เอาตามสะดวกเลยครับ ยังไงก็ได้ กับดูให้แน่ใจว่า Backend เราส่งข้อมูลไปข้างนอกได้จริง ๆ ไม่ติดอะไร

2. เตรียมค่า API Secret และ Measurement ID

ค่า API Secret จะต้องไปเอามาจากตัว Google Analytics UI วิธีการคือ

ไปที่หน้า Google Analytics UI Admin >>> Admin > Data collection and modification > Data Streams > Web stream details > Measurement Protocol API secrets > Create.

ค่า Measurement ID เอามาจาก Firebase Admin UI หรือ Google Analytics UI ก็ได้

Firebase Admin UI >>> Project settings > Your apps > Web apps > [measurementId]

Google Analytics UI >>> Admin > Data collection and modification > Data Streams > Web stream details

3. เตรียมค่า User ID และ Google Analytics Client ID ที่ได้มาจาก Frontend

มาถึงจุดนี้ ก็ได้เวลาที่เราจะเอา User ID และ Google Analytics Client ID ที่เราเก็บมาจาก Frontend ออกมาใช้แล้ว

type GoogleAnalyticsEvent = {
name: string;
params: any;
}

type GoogleAnalyticsPayload = {
client_id: string;
user_id?: string;
timestamp_micros?: number;
user_properties?: any;
events: GoogleAnalyticsEvent[];
}

async function sendEventToGA(
googleAnalyticsClientId: string,
googleAnalyticsUserId: string,
events: any[]
) {
try {
const data: GoogleAnalyticsPayload = {
client_id: googleAnalyticsClientId,
user_id: googleAnalyticsUserId,
events,
}
const response = await sendEventToGoogleAnalytics(data)
consola.log('payment.controller sendPaymentEventToGA ok response.status', response.status)
consola.log('payment.controller sendPaymentEventToGA ok response.data', stringify(response.data))
return response
} catch (error) {
consola.log('payment.controller sendPaymentEventToGA fail', error.message)
}
}

export async function sendEventToGoogleAnalytics (data: GoogleAnalyticsPayload) {
const endpoint = 'https://www.google-analytics.com/mp/collect'
const debugEndpoint = 'https://www.google-analytics.com/debug/mp/collect'
const config: AxiosRequestConfig = {
headers: {
'Content-Type': 'application/json',
},
params: {
measurement_id: GOOGLE_ANALYTIC_MEASUREMENT_ID,
api_secret: GOOGLE_ANALYTIC_API_SECRET,
},
}

consola.log('google-analytic.repo sendEventToGoogleAnalytics ok config', stringify(config))
consola.log('google-analytic.repo sendEventToGoogleAnalytics ok data', stringify(data))
return axios.post(endpoint, data, config)
}

ใน Code ตัวอย่างนี้ จะมี 2 Function หลัก คือ

  1. sendEventToGA() เป้าหมายคือ ทำหน้าที่เตรียมประกอบข้อมูล ก่อนส่งข้อมูล
  2. sendEventToGoogleAnalytics() เป้าหมายคือส่งข้อมูล

อันที่จริงจะเขียนรวมกันก็ได้นะครับ แต่ผมชอบแยกอย่างน้อย ออกเป็น 2 Layer แบบนี้ โดยแยกตัวประกอบข้อมูล กับตัวส่งข้อมูลออกจากกัน

ใน Code ตัวสมบูรณ์ จะมีตัว Data Builder แยกออกมาอีก ก่อนจะมาประกอบร่าง และส่งข้อมูลตามลำดับ

ดูผล

วิธีดูผลที่สะดวกที่สุด คือดูผ่าน Realtime Event ครับ ถ้าเราใช้ User ID และ Google Analytics Client ID อย่างถูกต้อง เราจะเป็น Offline Event ที่เราส่งขึ้นเอง ไปรวมอยู่ใน User คนเดียวกันได้อย่างถูกต้อง

ตรงนี้ต้องขออภัยที่ไม่สามารถ เอารูปตัวอย่างออกมาได้ เนื่องเป็นมันเป็นงานที่ทำจริง

มาถึงตรงนี้ อาจจะมีคนคาใจว่า จะใช้ User ID ทำไม ในเมื่อ ใช้แค่ Google Analytics Client ID ก็เพียงพอแล้ว คำตอบคือ เวลาที่เราเอาข้อมูลออกมาใช้ต่อ (ไม่ว่าจะเป็น Power BI หรือ Looker Studio) เราจะได้มี Property ตัวนี้ เอาไว้เป็นตัวเชื่อมกับข้อมูลของเราเองครับ

--

--