Nếu bạn đang chạy quảng cáo Facebook và phụ thuộc vào một dataset duy nhất để tracking toàn bộ chuyển đổi, bạn đang đặt cược tất cả vào một điểm lỗi duy nhất. Chỉ cần dataset đó bị vô hiệu hóa — dù vì vi phạm chính sách, bị report, hay lỗi kỹ thuật — toàn bộ dữ liệu machine learning mà Facebook đã tích lũy sẽ mất trắng.
Mục lục
ToggleGiải pháp? Bắn Conversions API (CAPI) đồng thời cho nhiều dataset qua GTM Server-Side. Và tin tốt là bạn có thể tự host hoàn toàn miễn phí trên server Ubuntu của mình.
Trong bài viết này, mình sẽ hướng dẫn bạn từ A đến Z cách thiết lập hệ thống này.
CAPI Là Gì Và Tại Sao Cần Server-Side?
Facebook Conversions API (CAPI)
Conversions API là phương thức gửi dữ liệu sự kiện (events) từ server của bạn trực tiếp đến server Facebook, thay vì thông qua trình duyệt người dùng như Pixel truyền thống.
Pixel truyền thống vs. CAPI
| Tiêu chí | Pixel (Browser-side) | CAPI (Server-side) |
|---|---|---|
| Gửi từ đâu | Trình duyệt người dùng | Server của bạn |
| Bị Ad-blocker chặn | ✅ Có | ❌ Không |
| Ảnh hưởng bởi iOS 14+ | ✅ Nặng | ❌ Ít |
| Độ chính xác | Trung bình | Cao |
| Dữ liệu user (email, phone) | Hạn chế | Đầy đủ, hash trước khi gửi |
Tại sao cần bắn CAPI cho nhiều dataset?
- Backup: Nếu dataset chính bị die, các dataset phụ vẫn tiếp tục nhận data
- Phân bổ chiến dịch: Mỗi dataset có thể phục vụ một nhóm quảng cáo khác nhau
- Tích lũy data: Dataset nào cũng có data → khi cần chuyển đổi, không bắt đầu từ số 0
Kiến trúc Tổng Quan
Khách truy cập website
│
▼
┌──────────────────────┐
│ GTM Web Container │ ← Chạy trên trình duyệt (WordPress)
│ (Browser-side) │
└──────────┬───────────┘
│ Forward events qua GA4 transport
▼
┌──────────────────────┐
│ GTM Server Container │ ← Chạy trên Ubuntu Server (Docker)
│ ss.yourdomain.com │
└──────────┬───────────┘
│ Facebook CAPI (server-to-server)
▼
┌──────────────────────┐
│ Facebook Servers │
│ Dataset 1 │
│ Dataset 2 │
│ Dataset N... │
└──────────────────────┘
Flow hoạt động:
- Khách truy cập website → GTM Web Container bắt các sự kiện ecommerce (xem sản phẩm, thêm giỏ, mua hàng…)
- GTM Web forward events lên GTM Server Container qua giao thức GA4
- GTM Server nhận events → gửi CAPI đồng thời đến tất cả dataset Facebook
Yêu Cầu Trước Khi Bắt Đầu
Trước khi bắt tay vào setup, bạn cần chuẩn bị:
- ✅ Server Ubuntu (tự host hoặc VPS) — đã cài Docker và docker-compose
- ✅ Domain với khả năng tạo subdomain (ví dụ:
ss.yourdomain.com) - ✅ Cloudflare quản lý DNS (dùng Cloudflare Tunnel để expose server an toàn, không cần mở port)
- ✅ Tài khoản Google Tag Manager với 2 container: 1 Web + 1 Server
- ✅ Facebook Business Manager với quyền truy cập các dataset cần tracking
- ✅ GTM4WP plugin (miễn phí) đã cài trên WordPress — để tự động push ecommerce events vào dataLayer
Phần 1: Deploy GTM Server Trên Ubuntu
Bước 1.1: Tạo Server Container trong GTM
- Truy cập tagmanager.google.com
- Bấm Create Container → đặt tên (ví dụ: “Server – CAPI”)
- Chọn Target platform: Server
- Chọn Manually provision tagging server
- Copy chuỗi Container Config (dạng
aWQ9R1RN...) → lưu lại
Bước 1.2: Tạo file Docker Compose
SSH vào server Ubuntu, tạo thư mục và file cấu hình:
mkdir -p ~/gtm-server
nano ~/gtm-server/docker-compose.yml
Dán nội dung sau (thay YOUR_CONTAINER_CONFIG bằng chuỗi ở bước 1.1):
version: '3.8'
services:
gtm-server:
image: gcr.io/cloud-tagging-10302018/gtm-cloud-image:stable
container_name: gtm-server
restart: always
ports:
- "8080:8080"
environment:
- CONTAINER_CONFIG=YOUR_CONTAINER_CONFIG
- RUN_AS_PREVIEW_SERVER=false
- PORT=8080
gtm-preview:
image: gcr.io/cloud-tagging-10302018/gtm-cloud-image:stable
container_name: gtm-preview
restart: always
ports:
- "8081:8081"
environment:
- CONTAINER_CONFIG=YOUR_CONTAINER_CONFIG
- RUN_AS_PREVIEW_SERVER=true
- PORT=8081
Bước 1.3: Chạy Docker
cd ~/gtm-server
docker-compose up -d
Kiểm tra:
# Xem container đang chạy
docker ps
# Test healthz
curl http://localhost:8080/healthz
# Kết quả mong đợi: ok
Bước 1.4: Expose qua Cloudflare Tunnel
Nếu server của bạn đứng sau NAT (mạng nhà, công ty) hoặc không muốn mở port trực tiếp, dùng Cloudflare Tunnel:
- Vào Cloudflare Zero Trust Dashboard
- Networks → Tunnels → chọn tunnel đang chạy → Configure
- Tab Public Hostname → Add a public hostname:
- Subdomain:
ss - Domain:
yourdomain.com - Service Type:
HTTP - URL:
localhost:8080
- Save
Lưu ý: Cloudflare Tunnel tự động tạo bản ghi DNS và cung cấp SSL — bạn không cần cấu hình thêm gì.
Kiểm tra: Truy cập https://ss.yourdomain.com/healthz → phải hiện chữ ok.
Phần 2: Lấy Access Token Từ Facebook
Mỗi dataset cần 1 Access Token riêng để GTM Server gửi CAPI. Lặp lại các bước sau cho từng dataset:
- Vào Facebook Events Manager
- Chọn dataset cần lấy token ở cột bên trái
- Bấm Settings (Cài đặt) ở menu phía trên
- Kéo xuống phần Conversions API
- Bấm Generate access token
- Copy chuỗi
EAA...→ lưu lại
Kết quả: Bạn sẽ có danh sách dạng:
Dataset 1: 111111111111111 → EAA...(token 1)...
Dataset 2: 222222222222222 → EAA...(token 2)...
Dataset 3: 333333333333333 → EAA...(token 3)...
Phần 3: Cấu Hình GTM Server Container
Truy cập tagmanager.google.com → chọn Server Container
Bước 3.1: Cài đặt Server Container URL
- Vào Admin → Container Settings
- Trường Server container URLs: nhập
https://ss.yourdomain.com - Save
Bước 3.2: Tạo GA4 Client
Client là thành phần “lắng nghe” và parse request từ GTM Web.
- Clients → New
- Tên:
GA4 Client - Client Type: chọn GA4
- Giữ mặc định → Save
Bước 3.3: Cài Template Facebook CAPI
- Templates → mục Tag Templates → Search Gallery
- Tìm:
Facebook Conversions API - Chọn template phổ biến nhất → Add to workspace
Bước 3.4: Tạo Trigger
- Triggers → New
- Tên:
All Events - Trigger Type: Custom → chọn All Events
- Save
Bước 3.5: Tạo CAPI Tag cho mỗi Dataset
Lặp lại bước này cho từng dataset:
- Tags → New
- Tên:
FB CAPI - Dataset 1(đổi số tương ứng) - Tag Type: Facebook Conversions API Tag
- Cấu hình:
- API Access Token: dán token tương ứng
- Pixel ID: nhập Pixel ID tương ứng
- Action Source:
website
- User Data (nếu template có):
- Bật Include user data hoặc điền các trường email, phone
- Đảm bảo
fbpvàfbccookies được gửi
- Triggering: chọn
All Events - Save
Kết quả: Bạn sẽ có N tag CAPI (mỗi dataset 1 tag), tất cả cùng trigger.
Phần 4: Cấu Hình GTM Web Container
Truy cập tagmanager.google.com → chọn Web Container (Nếu chưa có tạo 1 Web container mới, id của Container này sẽ được add vào website của bạn)
Bước 4.1: Tạo Variables
Cookie _fbp:
- Variables → New → loại 1st Party Cookie
- Tên:
Cookie - _fbp| Cookie Name:_fbp
Cookie _fbc:
- Tương tự → Tên:
Cookie - _fbc| Cookie Name:_fbc
Event ID (chống đếm trùng):
- Variables → New → loại Custom JavaScript
- Tên:
JS - Event ID - Code:
function() {
if (!window._currentEventId) {
window._currentEventId = new Date().getTime() + '.' + Math.floor(Math.random() * 1000000);
}
var id = window._currentEventId;
setTimeout(function() { window._currentEventId = null; }, 100);
return id;
}
Tạo Thêm 5 biến mới:
| Tên | Loại | Data Layer Variable Name |
|---|---|---|
DVL – ecommerce.currency | Data Layer Variable | ecommerce.currency |
DVL – ecommerce.value | Data Layer Variable | ecommerce.value |
DVL – ecommerce.items | Data Layer Variable | ecommerce.items |
DLV - user_data.email | Data Layer Variable | user_data.email |
DLV - user_data.phone_number | Data Layer Variable | user_data.phone_number |
Plugin GTM4WP không tự động push email/phone vào dataLayer (vì lý do bảo mật). Bạn cần thêm 1 đoạn code nhỏ vào WordPress.
Vào WordPress → Appearance → Theme File Editor (hoặc dùng plugin Code Snippets). Thêm đoạn code PHP sau vào file functions.php (hoặc tạo snippet mới):
// Push user data vào dataLayer cho GTM CAPI
add_action('wp_footer', function() {
if (is_checkout() && is_wc_endpoint_url('order-received')) {
global $wp;
$order_id = absint($wp->query_vars['order-received']);
$order = wc_get_order($order_id);
if ($order) {
$email = strtolower(trim($order->get_billing_email()));
$phone = preg_replace('/[^0-9+]/', '', $order->get_billing_phone());
$first_name = strtolower(trim($order->get_billing_first_name()));
$last_name = strtolower(trim($order->get_billing_last_name()));
?>
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'user_data': {
'email': '<?php echo esc_js($email); ?>',
'phone_number': '<?php echo esc_js($phone); ?>',
'first_name': '<?php echo esc_js($first_name); ?>',
'last_name': '<?php echo esc_js($last_name); ?>'
}
});
</script>
<?php
}
}
});
Bước 4.2: Tạo GA4 Forward Tag
Tag này forward dữ liệu lên GTM Server Container.
- Tags → New
- Tên:
GA4 - Forward to Server - Tag Type: Google Analytics: GA4 Event
- Cấu hình:
- Measurement ID: nhập GA4 ID bất kỳ (ví dụ
G-XXXXXXXXXX) — bắt buộc để tag hoạt động - Event Name:
{{Event}}
- Event Parameters (bấm Add Row):
| Parameter | Value |
|---|---|
x-fb-ck-fbp | {{Cookie - _fbp}} |
x-fb-ck-fbc | {{Cookie - _fbc}} |
event_id | {{JS - Event ID}} |
items | {{DLV - ecommerce.items}} |
value | {{DLV - ecommerce.value}} |
currency | {{DLV - ecommerce.currency}} |
user_data.email_address | {{DLV - user_data.email}} |
user_data.phone_number | {{DLV - user_data.phone_number}} |
| server_container_url | https://ss.yourdomain.com |
- Triggering: chọn tất cả trigger ecommerce events (
view_item,add_to_cart,begin_checkout,purchase) - Save
Lưu ý: Nếu bạn chưa tạo các event này thì hãy tham khảo bước 4.1 và 4.2 tại Bài viết này hoặc xem ngay bên dưới
Bước C5: Tạo Triggers cho Ecommerce Events (nếu chưa có)
Nếu bạn đã có trigger cho các event này (từ setup Pixel browser-side trước đó), bạn có thể dùng lại luôn.
Trigger 1: ViewContent
- Triggers → New → Custom Event
- Event name:
view_item - Save
Trigger 2: AddToCart
- Triggers → New → Custom Event
- Event name:
add_to_cart - Save
Trigger 3: InitiateCheckout
- Triggers → New → Custom Event
- Event name:
begin_checkout - Save
Trigger 4: Purchase
- Triggers → New → Custom Event
- Event name:
purchase - Save
Bước 4.3: Cập nhật Pixel Browser Tags (Deduplication)
Nếu bạn có tag Pixel browser-side, thêm eventID để Facebook không đếm trùng (Nếu không có thì bỏ qua bước này):
Trước:
fbq('track', 'Purchase', {value: 500000, currency: 'VND'});
Sau:
fbq('track', 'Purchase', {value: 500000, currency: 'VND'}, {eventID: {{JS - Event ID}}});
Quan trọng:
eventIDtrong Pixel browser phải trùng vớievent_idgửi qua CAPI. Facebook sẽ tự động loại bỏ event trùng lặp (deduplication).
Phần 5: Test Và Go-live
Bước 5.1: Preview cả 2 Container
- GTM Server Container → bấm Preview → để tab mở
- GTM Web Container → bấm Preview → nhập URL website → Connect
Bước 5.2: Thực hiện test
Trên website đang preview:
- Xem 1 sản phẩm → kiểm tra
view_item - Thêm vào giỏ → kiểm tra
add_to_cart - Vào checkout → kiểm tra
begin_checkout - Hoàn tất đơn hàng → kiểm tra
purchase
Bước 5.3: Xác nhận trên Facebook
- Vào Events Manager → chọn từng dataset
- Tab Test Events → kiểm tra events có hiện với nguồn Server
- Nếu thấy cả Browser + Server cho cùng Event ID → dedup hoạt động ✅
Bước 5.4: Publish
- GTM Server Container → Submit → Publish
- GTM Web Container → Submit → Publish
Khắc Phục Sự Cố Thường Gặp
GTM Server không nhận events
- Kiểm tra
https://ss.yourdomain.com/healthz→ phải trả vềok - Kiểm tra Docker:
docker ps→ container phải đang chạy - Kiểm tra Server Container URL trong GA4 tag (GTM Web) đã đúng chưa
Facebook trả lỗi trong CAPI tag
- Xác nhận Access Token còn hiệu lực
- Kiểm tra Pixel ID đúng chưa
- Lỗi
Invalid parameter→ kiểm tra format event data
Event Match Quality thấp
- Đảm bảo gửi cookies
_fbp,_fbcqua parameters - Gửi thêm email, phone từ checkout data
- Facebook tự hash trước khi so sánh — bạn không cần hash thủ công
Restart sau khi server reboot
cd ~/gtm-server && docker-compose up -d
Kết Luận
Việc setup Facebook CAPI cho nhiều dataset qua GTM Server-Side tuy cần nhiều bước, nhưng mang lại những lợi ích rõ rệt:
- Tracking chính xác hơn — không bị ảnh hưởng bởi ad-blocker hay iOS 14+
- Backup an toàn — nhiều dataset nhận data đồng thời, không lo mất trắng
- Chi phí $0 — self-host trên server Ubuntu sẵn có
- Kiểm soát hoàn toàn — dữ liệu đi qua server của bạn trước khi đến Facebook
Với kiến trúc này, bạn có thể yên tâm scale chiến dịch quảng cáo mà không sợ rủi ro từ việc phụ thuộc vào một dataset duy nhất.
Bài viết được cập nhật lần cuối: Tháng 4/2026