文章:
We will show you how to set up automatic data export from Kwiga to Google Sheets.
您可以使用自动化为各种事件设置数据导出(可将添加联系人、添加标签、购买成功或失败等指定为事件;完整的事件列表请见文章中)。
此外,使用小组件时,您也可以选择发送 webhook;流程保持不变。
主要步骤:
-
创建一个文件并将脚本添加到其中
-
创建一个 web app 并获取用于发送 webhook 的链接
-
在 Kwiga 中使用自动化,或在小组件中通过表单提交来设置 webhook 发送。
整个过程已在视频中演示,且不需要编程知识。只需按照提供的步骤操作;如果遇到问题,请联系支持团队。
步骤 1:创建一个用于接收来自 Kwiga 数据的文件
打开Google Sheets,创建一个新文件,然后打开脚本编辑器。
将打开一个新窗口,您需要把脚本粘贴到其中的编辑器中。您可以通过链接下载该脚本(或复制文章底部的文本)。您需要删除编辑器中已有的所有文本。
最终结果:
步骤 2:创建一个 web app 并获取用于发送 webhook 的链接
在同一个脚本编辑器中,找到 Deploy 按钮并选择 New deployment
选择 Web app 作为类型,并在 Who has access 下拉列表中将其设置为 Everyone,然后点击 Deploy。
这样,您将获得 Web App URL,之后需要将其添加到 Kwiga 中。
步骤 3:在 Kwiga 中设置数据发送
点击顶部菜单中的 All solutions 按钮并选择 Automation。创建一个新的触发器,并选择将启动自动化的事件。可以是添加联系人、添加标签、支付或任何其他事件。
之后,向下滚动,在操作中选择 Webhook - Send data。在链接字段中填写 Web App URL,请求类型设为 POST,并选择应导出到表格的字段。
保存后,所有步骤就完成了。
或者,您也可以从小组件设置 webhook 发送;这在使用 Form 元素时可用。勾选 Additionally send to a third-party service 选项,然后在打开的表单中添加链接,请求类型设为 POST,并选择要发送的参数。此列表中只会显示表单(该小组件)中存在的参数。
Google Sheets脚本如何处理Webhook
- 首次调用Webhook时,会根据传入数据的键自动创建表头
- 如果表中已有表头并需要开始接收新的数据字段,请手动将这些表头添加到表中
- 可以在表中交换表头的位置 - 脚本会自动识别它们的位置
- 默认情况下,脚本在每次接收到Webhook时添加新记录
- 如果在keyColumns中指定字段,脚本将更新现有记录或在未找到匹配项时添加新记录
- ⚠️ 重要:修改脚本后,必须在Google Apps Script中重新部署并更新Webhook链接
选择表单的工作表:
- 默认使用活动工作表
- 可以通过Webhook参数重新定义:
- "sheet_name": "工作表名称" - 通过名称选择工作表
- "sheet_index": 2 - 通过编号选择工作表(从1开始)
// ============================================================
// 脚本设置
// ============================================================
// 检查重复项 - 指定字段以查找现有记录
// 使用示例:
// var keyColumns = ["email"]; - 通过email检查
// var keyColumns = ["order_id"]; - 通过订单ID检查
// var keyColumns = ["email", "order_id"]; - 通过多个字段检查
var keyColumns = []; // 重复项检查已禁用
// ============================================================
// 发送响应的功能
function sendResponse(success, message) {
var response = {
"status": success ? "success" : "error",
"message": message
};
return ContentService.createTextOutput(JSON.stringify(response))
.setMimeType(ContentService.MimeType.JSON);
}
// 获取记录数据的目标页面
function getTargetSheet(hook_data) {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
// 检查是否指定了页面名称
if (hook_data && hook_data.sheet_name) {
try {
var sheet = spreadsheet.getSheetByName(hook_data.sheet_name);
if (sheet) {
return sheet;
}
} catch (error) {
// 页面未找到
}
}
// 检查是否指定了页面编号
if (hook_data && hook_data.sheet_index && !isNaN(hook_data.sheet_index)) {
try {
var sheets = spreadsheet.getSheets();
var index = parseInt(hook_data.sheet_index) - 1; // 转换为从0开始的索引
if (index >= 0 && index < sheets.length) {
return sheets[index];
}
} catch (error) {
// 无效的页面索引
}
}
// 默认使用活动页面
return SpreadsheetApp.getActiveSheet();
}
// 根据传入数据创建表格标题
function populateHeaders(hook_data, sheet) {
if (!hook_data || typeof hook_data !== 'object') {
return false;
}
if (!sheet) {
sheet = getTargetSheet(hook_data);
}
var last_row = Math.max(sheet.getLastRow(), 1);
sheet.insertRowAfter(last_row);
var headers_row = ['timestamp'];
var hook_data_keys = Object.keys(hook_data);
for (var i = 0; i < hook_data_keys.length; i++) {
headers_row.push(hook_data_keys[i]);
}
sheet.appendRow(headers_row);
SpreadsheetApp.flush();
return true;
}
// 处理传入的webhook
function doPost(e) {
var hook_load = null;
// 检查POST数据的存在
if (!e || !e.postData || !e.postData.contents) {
return sendResponse(false, "没有要处理的数据");
}
// 解析JSON数据
try {
hook_load = JSON.parse(e.postData.contents);
} catch (error) {
return sendResponse(false, "JSON数据解析错误");
}
// 验证收到的数据
if (!hook_load || typeof hook_load !== 'object' || Object.keys(hook_load).length === 0) {
return sendResponse(false, "收到的数据不正确或为空");
}
try {
// 获取目标页面
var sheet = getTargetSheet(hook_load);
if (!sheet) {
return sendResponse(false, "未能找到指定的页面");
}
// 如果表格为空则创建标题
if (sheet.getLastColumn() === 0) {
populateHeaders(hook_load, sheet);
}
var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
if (headers.length === 0 || headers[0] === "") {
populateHeaders(hook_load, sheet);
headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
}
// 检查重复项
var data = [];
var targetRow = -1;
var numRows = sheet.getLastRow() - 1;
if (keyColumns.length > 0 && numRows > 0) {
data = sheet.getRange(2, 1, numRows, sheet.getLastColumn()).getValues();
for (var r = 0; r < data.length; r++) {
var row = data[r];
var match = true;
for (var k = 0; k < keyColumns.length; k++) {
var key = keyColumns[k];
var idx = headers.indexOf(key);
if (idx === -1 || row[idx] != hook_load[key]) {
match = false;
break;
}
}
if (match) {
targetRow = r + 2; // 标题记录
break;
}
}
}
// 准备记录数据
var new_sheet_row = new Array(headers.length).fill('');
for (var h = 0; h < headers.length; h++) {
var key = headers[h];
if (key === 'timestamp') {
new_sheet_row[h] = new Date();
} else if (hook_load.hasOwnProperty(key)) {
new_sheet_row[h] = hook_load[key];
}
}
// 将数据保存到表格
if (targetRow > -1) {
sheet.getRange(targetRow, 1, 1, new_sheet_row.length).setValues([new_sheet_row]);
} else {
sheet.appendRow(new_sheet_row);
}
SpreadsheetApp.flush();
return sendResponse(true, "数据已成功保存");
} catch (error) {
return sendResponse(false, "保存数据时出错:" + error.message);
}
}