Kéo báo cáo vào Google Sheets¶
Dùng Apps Script — không cần cài gì, chạy theo lịch ngay trong Google.
Đừng dùng IMPORTDATA hay IMPORTJSON
Những hàm đó không gửi được header, nên không mang được X-API-Key. Ngoài
ra chúng chạy lại mỗi khi sheet tính lại — đốt hạn mức rất nhanh.
1. Mở Apps Script¶
Trong Google Sheet: Tiện ích mở rộng → Apps Script.
2. Lưu API key an toàn¶
Dán vào editor, sửa giá trị, chạy một lần, rồi xoá hàm này đi:
function luuBiMat() {
PropertiesService.getScriptProperties().setProperties({
LOGIDATA_API_KEY: 'ld_live_...',
LOGIDATA_ACCOUNT_ID: 'ldc_9fK2xQ...',
ADVERTISER_ID: '7001234567890',
});
}
Cách này giữ key ngoài nội dung sheet, nên người được chia sẻ sheet không đọc được key.
3. Script kéo dữ liệu¶
const BASE = 'https://api.logidata.vn/v1/tiktok-ads';
function goi(path, params) {
const p = PropertiesService.getScriptProperties();
const qs = Object.keys(params)
.map(k => encodeURIComponent(k) + '=' + encodeURIComponent(params[k]))
.join('&');
const res = UrlFetchApp.fetch(BASE + path + '?' + qs, {
headers: {
'X-API-Key': p.getProperty('LOGIDATA_API_KEY'),
'X-Account-Id': p.getProperty('LOGIDATA_ACCOUNT_ID'),
},
muteHttpExceptions: true, // để tự đọc body lỗi thay vì bị ném ngoại lệ
});
const code = res.getResponseCode();
const body = JSON.parse(res.getContentText());
if (code >= 400) {
throw new Error(body.error.code + ': ' + body.error.message +
' (request_id=' + body.error.request_id + ')');
}
if (body.code !== 0) { // TikTok trả 200 kèm lỗi nghiệp vụ
throw new Error('TikTok ' + body.code + ': ' + body.message);
}
return body.data;
}
function ngay(luiBaoNhieu) {
const d = new Date();
d.setDate(d.getDate() - luiBaoNhieu);
return Utilities.formatDate(d, 'Asia/Ho_Chi_Minh', 'yyyy-MM-dd');
}
function capNhatBaoCao() {
const p = PropertiesService.getScriptProperties();
const data = goi('/v1.3/report/integrated/get/', {
advertiser_id: p.getProperty('ADVERTISER_ID'),
report_type: 'BASIC',
data_level: 'AUCTION_CAMPAIGN',
dimensions: '["campaign_id","stat_time_day"]',
metrics: '["spend","impressions","clicks"]',
// Kéo lại 7 ngày: TikTok còn điều chỉnh số liệu tới 48 giờ sau
start_date: ngay(7),
end_date: ngay(1),
page_size: 1000,
});
const rows = data.list.map(it => [
it.dimensions.stat_time_day.slice(0, 10),
it.dimensions.campaign_id,
parseFloat(it.metrics.spend),
parseInt(it.metrics.impressions, 10),
parseInt(it.metrics.clicks, 10),
]);
const sheet = SpreadsheetApp.getActive().getSheetByName('TikTok Ads')
|| SpreadsheetApp.getActive().insertSheet('TikTok Ads');
sheet.clear();
sheet.getRange(1, 1, 1, 5)
.setValues([['Ngày', 'Campaign ID', 'Chi phí', 'Hiển thị', 'Click']])
.setFontWeight('bold');
if (rows.length) {
sheet.getRange(2, 1, rows.length, 5).setValues(rows);
}
sheet.getRange('C2:C').setNumberFormat('#,##0');
SpreadsheetApp.getActive().toast(rows.length + ' dòng đã cập nhật');
}
4. Chạy tự động hằng ngày¶
Trong Apps Script: Trigger (biểu tượng đồng hồ) → Add Trigger
| Function | capNhatBaoCao |
| Event source | Time-driven |
| Type | Day timer |
| Time of day | 6am – 7am |
Lần chạy đầu Google sẽ hỏi cấp quyền cho script — đó là quyền của script với sheet của bạn, không liên quan tới Logidata hay TikTok.
5. Thêm tên campaign¶
Báo cáo chỉ trả về ID. Lấy tên rồi ghép bằng map:
function layTenCampaign(advertiserId) {
const ten = {};
let page = 1, tongTrang = 1;
do {
const d = goi('/v1.3/campaign/get/',
{advertiser_id: advertiserId, page: page, page_size: 1000});
d.list.forEach(c => { ten[c.campaign_id] = c.campaign_name; });
tongTrang = d.page_info.total_page;
page++;
} while (page <= tongTrang);
return ten;
}
Gọi một lần đầu capNhatBaoCao() rồi tra ten[it.dimensions.campaign_id] khi
dựng từng dòng.
Giới hạn 6 phút của Apps Script
Mỗi lần chạy tối đa 6 phút. Nếu bạn có nhiều advertiser, tách thành nhiều hàm với trigger ở các khung giờ khác nhau, thay vì nhồi hết vào một hàm.
```