apointoo

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Apointoo integration

Apointoo 集成

Skill v1.0.1 · verified against the live Apointoo API on 2026-06-26. See
CHANGELOG.md
. A major bump = a breaking change to the integration contract below.
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验证。查看
CHANGELOG.md
。版本号的major升级意味着以下集成协议会发生破坏性变更。
Apointoo可将预约/潜在客户表单转化为规范的Google Ads/Meta转化数据。本Skill展示了如何将任意项目连接到你的Apointoo租户。
你需要: 一个带有租户的Apointoo账户。从Apointoo控制台获取你的tenant slugpublishable 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/json
Body:
json
{
  "lead": { "email": "...", "phone": "...", "name": "...", "message": "..." },
  "attribution": { "gclid": "...", "utm_source": "...", "utm_medium": "...", "utm_campaign": "..." },
  "marketingConsent": true
}
  • Provide at least one of
    lead.email
    or
    lead.phone
    (otherwise the API returns
    422
    ).
  • Success →
    201 { "submissionId": "...", "kind": "contact" }
    .
  • Intake is origin-gated: the request
    Origin
    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.
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
    lead.phone
    中的至少一项(否则API会返回
    422
    错误)。
  • 请求成功会返回
    201 { "submissionId": "...", "kind": "contact" }
  • Intake接口受源限制:请求的
    Origin
    必须在租户的允许源列表中,或者通过自己的后端路由代理,以服务端调用的方式发起请求(避免在浏览器中暴露密钥)。

2. Environment (recommended names)

2. 环境变量(推荐命名)

VarPurpose
APOINTOO_DASHBOARD_URL
API base (default
https://dash.apointoo.com
)
APOINTOO_TENANT_SLUG
your tenant slug
APOINTOO_TENANT_KEY
publishable key — server-side (recommended)
NEXT_PUBLIC_APOINTOO_TENANT_KEY
the key for pure client-side calls (it's origin-gated)
NEXT_PUBLIC_GTM_ID
your GTM container id
Never hardcode these in component code — read them from env.
变量名用途
APOINTOO_DASHBOARD_URL
API基础地址(默认值为
https://dash.apointoo.com
APOINTOO_TENANT_SLUG
你的租户slug
APOINTOO_TENANT_KEY
可发布密钥 — 推荐在服务端使用
NEXT_PUBLIC_APOINTOO_TENANT_KEY
纯客户端调用时使用的密钥(受源限制保护)
NEXT_PUBLIC_GTM_ID
你的GTM容器ID
切勿在组件代码中硬编码这些值——从环境变量中读取。

3. Fire the conversion via GTM (not direct gtag/fbq)

3. 通过GTM触发转化事件(不直接使用gtag/fbq)

On a successful
201
, read the body and push to the dataLayer so GTM can fire your ad tags:
js
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
generate_lead
, bound to your GA4 event tag and your Google Ads (and/or Meta) conversion tag. Use
event_id
/
transaction_id
for deduplication. Keep the conversion id + label in GTM, not in code.
当请求返回
201
成功状态时,读取响应体并推送到dataLayer,以便GTM触发你的广告标签:
js
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中:创建一个针对
generate_lead
的自定义事件触发器,绑定到你的GA4事件标签以及Google Ads(和/或Meta)转化标签。使用
event_id
/
transaction_id
进行去重。将转化ID和标签保存在GTM中,不要硬编码到代码里。

Rules that keep it clean

保持规范的规则

  • All tracking via GTM + dataLayer — never hardcoded
    gtag()
    /
    fbq()
    in components.
  • 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`事件仅触发一次,且你的转化标签已接收到该事件。