apointoo
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseApointoo integration
Apointoo 集成
Skill v1.0.1 · verified against the live Apointoo API on 2026-06-26. See. A major bump = a breaking change to the integration contract below.CHANGELOG.md
Apointoo turns booking/lead forms into clean Google Ads / Meta conversions. This skill shows how to
connect any project to your Apointoo tenant.
You need: an Apointoo account with a tenant. Get your tenant slug and publishable key
from your Apointoo dashboard, and add your site's origin to the tenant's allowed origins.
Skill v1.0.1 · 已在2026-06-26基于Apointoo实时API验证。查看。版本号的major升级意味着以下集成协议会发生破坏性变更。CHANGELOG.md
Apointoo可将预约/潜在客户表单转化为规范的Google Ads/Meta转化数据。本Skill展示了如何将任意项目连接到你的Apointoo租户。
你需要: 一个带有租户的Apointoo账户。从Apointoo控制台获取你的tenant slug和publishable key,并将你的站点源添加到租户的允许源列表中。
1. Send leads to the intake API (any language)
1. 向intake API发送潜在客户数据(支持任意语言)
POST https://dash.apointoo.com/api/intake/<your-slug>/contact
Header: X-Apointoo-Tenant-Key: <your publishable key>
Content-Type: application/jsonBody:
json
{
"lead": { "email": "...", "phone": "...", "name": "...", "message": "..." },
"attribution": { "gclid": "...", "utm_source": "...", "utm_medium": "...", "utm_campaign": "..." },
"marketingConsent": true
}- Provide at least one of or
lead.email(otherwise the API returnslead.phone).422 - Success → .
201 { "submissionId": "...", "kind": "contact" } - Intake is origin-gated: the request must be in your tenant's allowed origins, or call it server-side (keep the key off the browser) by proxying through your own backend route.
Origin
POST https://dash.apointoo.com/api/intake/<your-slug>/contact
Header: X-Apointoo-Tenant-Key: <your publishable key>
Content-Type: application/json请求体:
json
{
"lead": { "email": "...", "phone": "...", "name": "...", "message": "..." },
"attribution": { "gclid": "...", "utm_source": "...", "utm_medium": "...", "utm_campaign": "..." },
"marketingConsent": true
}- 必须提供或
lead.email中的至少一项(否则API会返回lead.phone错误)。422 - 请求成功会返回。
201 { "submissionId": "...", "kind": "contact" } - Intake接口受源限制:请求的必须在租户的允许源列表中,或者通过自己的后端路由代理,以服务端调用的方式发起请求(避免在浏览器中暴露密钥)。
Origin
2. Environment (recommended names)
2. 环境变量(推荐命名)
| Var | Purpose |
|---|---|
| API base (default |
| your tenant slug |
| publishable key — server-side (recommended) |
| the key for pure client-side calls (it's origin-gated) |
| your GTM container id |
Never hardcode these in component code — read them from env.
| 变量名 | 用途 |
|---|---|
| API基础地址(默认值为 |
| 你的租户slug |
| 可发布密钥 — 推荐在服务端使用 |
| 纯客户端调用时使用的密钥(受源限制保护) |
| 你的GTM容器ID |
切勿在组件代码中硬编码这些值——从环境变量中读取。
3. Fire the conversion via GTM (not direct gtag/fbq)
3. 通过GTM触发转化事件(不直接使用gtag/fbq)
On a successful , read the body and push to the dataLayer so GTM can fire your ad tags:
201js
const { submissionId } = await res.json()
window.dataLayer = window.dataLayer || []
window.dataLayer.push({
event: 'generate_lead',
form_id: 'your_form',
event_id: crypto.randomUUID(), // GA4/Ads dedupe id
transaction_id: submissionId, // ties the hit to the server record for offline dedupe
value: 1,
currency: 'EUR',
gclid, fbclid, // from your captured attribution
})Then in GTM: a Custom Event trigger on , bound to your GA4 event tag and your
Google Ads (and/or Meta) conversion tag. Use / for deduplication.
Keep the conversion id + label in GTM, not in code.
generate_leadevent_idtransaction_id当请求返回成功状态时,读取响应体并推送到dataLayer,以便GTM触发你的广告标签:
201js
const { submissionId } = await res.json()
window.dataLayer = window.dataLayer || []
window.dataLayer.push({
event: 'generate_lead',
form_id: 'your_form',
event_id: crypto.randomUUID(), // GA4/Ads去重ID
transaction_id: submissionId, // 将点击记录与服务端记录关联以实现离线去重
value: 1,
currency: 'EUR',
gclid, fbclid, // 来自捕获的归因数据
})然后在GTM中:创建一个针对的自定义事件触发器,绑定到你的GA4事件标签以及Google Ads(和/或Meta)转化标签。使用/进行去重。将转化ID和标签保存在GTM中,不要硬编码到代码里。
generate_leadevent_idtransaction_idRules that keep it clean
保持规范的规则
- All tracking via GTM + dataLayer — never hardcoded /
gtag()in components.fbq() - IDs, keys, endpoints from env — never hardcoded.
- One conversion source per event — fire it client-side (GTM) or server-side, not both (double-count).
- Respect consent — gate ad-click data on the user's choice (Consent Mode v2).
- 所有追踪通过GTM + dataLayer实现 — 切勿在组件中硬编码/
gtag()。fbq() - ID、密钥、端点从环境变量获取 — 切勿硬编码。
- 每个事件仅一个转化源 — 在客户端(GTM)或服务端触发转化,不要同时在两端触发(避免重复统计)。
- 尊重用户授权 — 根据用户的选择(Consent Mode v2)控制广告点击数据的收集。
Verify
验证方法
bash
curl -X POST "$APOINTOO_DASHBOARD_URL/api/intake/$SLUG/contact" \
-H "X-Apointoo-Tenant-Key: $KEY" -H 'content-type: application/json' \
-d '{"lead":{"email":"test@example.com"},"attribution":{}}'bash
curl -X POST "$APOINTOO_DASHBOARD_URL/api/intake/$SLUG/contact" \
-H "X-Apointoo-Tenant-Key: $KEY" -H 'content-type: application/json' \
-d '{"lead":{"email":"test@example.com"},"attribution":{}}'expect: 201 {"submissionId":"...","kind":"contact"}
预期结果:201 {"submissionId":"...","kind":"contact"}
Then in GTM Preview, confirm `generate_lead` fires once and your conversion tag receives it.然后在GTM预览模式中,确认`generate_lead`事件仅触发一次,且你的转化标签已接收到该事件。