@clakta / javascript
浏览器的官方Clakta SDK。
Clakta是一个为现代企业打造的现代销售和广告跟踪平台。通过现代而强大的平台,获得准确的数据并了解哪些广告表现最佳,哪些影响者销售最多。
网站
框架无关跟踪任何网站或web应用程序。零依赖,工作与一个bundle或单个 <script> 标签。
安装
npm install @clakta/javascript
pnpm add @clakta/javascript
yarn add @clakta/javascript
或者直接从CDN加载-不需要构建步骤:
<script src="https://cdn.clakta.com/script.js" defer></script>
如果你想要自己控制升级,就锁定一个特定的版本:
<script src="https://cdn.clakta.com/v1.0.8/script.js" defer></script>
使用
在您打电话之前,我们不会收取任何费用 init,所以尽早调用它——最好是在你的应用程序渲染之前——并传递你的脚本id。其他的都是可选的。
import clakta from "@clakta/javascript"
clakta.init({ id: "YOUR_SCRIPT_ID" })
命名导入也可以工作,如果你喜欢它们或者想要更小的包:
import { init, trackEvent } from "@clakta/javascript"
init({ id: "YOUR_SCRIPT_ID" })
trackEvent("hero-cta", "click")
使用脚本标签
CDN构建公开了一个 Clakta 全球:
<script src="https://cdn.clakta.com/script.js" defer></script>
<script>
window.addEventListener("load", function () {
Clakta.init({ id: "YOUR_SCRIPT_ID" })
})
</script>
要完全跳过引导,请添加 data-id 标签,SDK在加载时初始化自己:
<script
src="https://cdn.clakta.com/script.js"
data-id="YOUR_SCRIPT_ID"
defer
></script>
如果你坚持 data-id 上了标签却想打电话 init 你自己,加上标签不能表达的选项,添加 data-auto-init="false". 否则,标记将首先初始化 init 调用被视为重复调用而忽略。
后 init 运行时,完整的API也可用 window.clakta 方便内联脚本,谷歌标签管理器,或任何不能导入模块的代码:
<button onclick="window.clakta.trackEvent('hero-cta', 'click')">Buy now</button>
选项
| 选项 | 类型 | 默认的 | 描述 |
|---|---|---|---|
id | string | - - - - - - | 必需的。 您的Clakta脚本id。 |
apiHost | string | https://api.clakta.com | 覆盖API主机。跟踪/配置使用 https://t.clakta.com 默认情况下;Stripe停留在api.clakta.com上。 |
debug | boolean | false | 详细控制台日志记录。 |
consent | boolean | 按访客地点划分 | 访问者是否同意使用第一方标识符。看到 同意. |
它是如何工作的
在 init SDK询问Clakta API这个源应该如何收集数据——跟踪模式加上自动跟踪的事件。这些都是仪表板设置,所以它们是在运行时解决的,而不是嵌入到构建中。
两个结果值得了解:
- 在该配置解析之前不会发送任何内容。 在此期间,你可以打电话
identify之后init(比如)被缓冲,并在完成后重新播放。 - 如果配置不能解析 -未知的脚本id,或无法访问的API - SDK保持惰性,根本不发送任何信息,而不是猜测访问者可能被跟踪的方式。
跟踪模式
每个项目收集数据的两种模式之一,设置在您的Clakta仪表板:
| 模式 | 行为 |
|---|---|
privacy_friendly | 没有cookie或第一方标识符,也没有浏览器存储。服务器派生会话。 identify 是不可行的。 |
full_attribution | 存储支持的会话,持久的访问者id和更丰富的客户端上下文,受制于访问者的同意。 |
该模式不是客户端选项-它来自项目设置,因此它在安装SDK的每个表面上保持一致。
下 full_attribution 在征得同意的情况下,SDK会保留一个单一的第一方cookie, _clakta,在您的可注册域名(与localStorage副本)。它保存访问者id(在创建一年后过期,以后的访问不会延长)、当前会话(在30分钟不活动后结束)和点击令牌(clkt)。访问者id是当一个人的IP在访问过程中改变时(在移动网络上是常规的),或者当他们在你的子域之间移动时,使一个人被计算一次的原因。第二块饼干, _clakta_consent,记住访问者对cookie横幅的回答;看到 同意.
早期版本的SDK将这些值保存在单独的cookie中(clakta_session_id, clakta_visitor_id, clakta_has_visited 和 clakta_landing_page). 当一个同意的访问者第一次返回时,他们的id将被转移到 _clakta 旧的cookie会被删除,所以没有人会被算作新访客。
同意
同意仅在以下情况下有效 full_attribution;在 privacy_friendly 无论如何都不使用任何标识符。
除非你设置它,否则同意跟随访问者的位置。欧盟、欧洲经济区、英国和瑞士的游客——以及任何地理位置不明的游客——都可以开始 没有 同意,正如GDPR和电子隐私规则所要求的那样,并且只有在您的cookie横幅调用时才会被识别 updateConsent(true). 其他所有人都从它开始,仍然可以下降。当SDK加载其配置时,Clakta从请求中计算出位置;设备上没有存储任何信息。
未经同意的访客仍然会被匿名统计:他们的设备上不会存储任何内容,也不会发送会话或访客id, Clakta会记录访问 privacy_friendly 方式-服务器派生会话和每天更改的访问者id。其他的一切都被记录下来:带有UTM标签的页面浏览量, clkt 广告点击id (gclid, fbclid),点击,滚动和表单提交,以及购物漏斗 pageViewWithProduct, addToCart, initiateCheckout 和 purchase -只有 customer 遗漏了细节。
自己在init -处设置起始值 false 问每一个来访者他们在哪里,或者 true 如果SDK只在访问者接受后加载:
clakta.init({ id: "YOUR_SCRIPT_ID", consent: false })
或者,在script标签上,使用 data-consent:
<script
src="https://cdn.clakta.com/script.js"
data-id="YOUR_SCRIPT_ID"
data-consent="false"
defer
></script>
当访问者在你的cookie横幅上做出选择时更新它:
import { getConsent, updateConsent } from "@clakta/javascript"
updateConsent(true) // or clakta.consent.update(true)
getConsent() // => true
getConsent() 报告 false 直到做出选择-由您,由访问者,或由他们的位置一旦配置加载。
当访问者回答时发生了什么
答案记在a里 _clakta_consent cookie在您的可注册域名上,由每个子域名共享,并从最新答案起保留一年,并在localStorage副本中保存,没有到期,在cookie消失后将其保留在网站上。之后的页面从它们的第一个事件开始应用它,所以你的横幅只需要在访问者给出答案时报告一次答案;在每个页面上再次报告它是无害的,并且会更新cookie。 拒绝也会被记住——这是在下一页上尊重它所需要的——这是SDK在未经同意的情况下存储的一件事。没有存储任何东西 privacy_friendly 来源。
你自己的 consent 价值比记住答案更重要。 true 说客人接受了。 false 让每个访问者保持匿名,不管他们之前回答了什么,直到他们接受当前页面 false,你的横幅必须呼叫 updateConsent(true) (或一组 window.claktaConsent),以供接受的访客使用。
当访问者接受中途访问时,SDK立即启动其识别的会话并记录其中的当前页面。会话获取其click令牌(clkt)从这个页面加载开始的URL -访问者从你的广告到达的那个-所以接下来的销售保留了它的广告来源。该页面浏览量还会命名同一页面的匿名浏览量,Clakta会删除匿名浏览量,这样页面就会被统计一次:尚未回答横幅的访问者的页面浏览量会被保留60秒,直到他们到达你的仪表板,仪表板覆盖了大多数横幅的答案。拒绝的访问者的页面浏览量不会被保留。 稍后回答的访问者在两个会话中都会记录该页面。在他们接受的页面之前浏览的页面停留在访问的匿名部分,因为未经他们同意,任何内容都不能存储。
横幅可以在延迟脚本标签加载之前回答,当 clakta.consent 还不存在。集 window.claktaConsent 相反,和 init 把它从其他所有东西中挑选出来——起始值、记住的答案和访问者的位置:
window.claktaConsent = true
撤销许可立即清除SDK存储的所有标识符,后续事件如上所述匿名记录。
网址内的个人资料
每个事件都带有页面URL,因此其中用于命名人员或用作凭据的值将被替换为 redacted 在离开浏览器之前,无论访问者是否同意:任何包含电子邮件地址的值,以及诸如 email, phone, token, password 或者 first_name. 这同样适用于引用、出站链接和表单操作。不需要替换的url被原样发送。
自动跟踪
初始化后,SDK只安装你的项目在仪表板中启用的监听器:
- 页面浏览量 -跟踪负载和每个SPA导航(
pushState,replaceState,popstate,hashchange). 对同一URL的重复视图是不允许的。 - 页面上的时间 -仅在页面可见时计数,并在访问者隐藏标签,关闭页面或在应用程序中导航时报告,因此访问的最后一页也会计时。自带页面浏览量;它自己没有开关。
- 点击 -出站链接,加上您明确选择加入的任何元素
data-clkt-track-click. 其他地方的点击将被忽略,因此您不会为页面上的每次点击获得一个事件。 - 滚动深度 - 25% / 50% / 75% / 100%里程碑,在短页面的出口处发出最远深度。
- 表单提交 -表单id、操作和字段 数. 在任何跟踪模式中,都不会收集字段值。
<button data-clkt-track-click id="hero-cta">Buy now</button>
无论是否开启自动跟踪,下面的所有内容都可以手动调用。
API
pageView()
记录当前URL的页面视图。当自动页面视图关闭时,或者对于虚拟页面视图,您的框架不通过历史API路由时,非常有用。
clakta.pageView()
trackEvent(trackingId, eventType, metadata?)
跟踪当前会话中的自定义事件。
clakta.trackEvent("hero-cta", "click", { variant: "A" })
clakta.trackEvent("onboarding", "signup", { plan: "pro" })
identify(customer)
附加客户的详细信息到会话-调用它当你知道谁的访客是,例如在登录或注册。至少有一个 externalId, claktaCustomerId,或者 email 是必需的;任何额外的字段都被转发为自由形式的特征。
clakta.identify({
externalId: "user_123",
email: "[email protected]",
name: "Ada Lovelace",
plan: "pro", // extra fields become traits
})
识别访问者与匿名收集是相反的,所以在 privacy_friendly 当同意被拒绝时。
电子商务
三个漏斗事件覆盖了通向销售的道路。每个都保留了您传递的任何额外的元数据,因此您可以将平台已经使用的形状交给它。
// Add to cart — no order exists yet
clakta.addToCart({
products: [{ id: "42", name: "Tee", price: 29.99, quantity: 2 }],
totalPrice: 59.98,
currency: "USD",
})
// Checkout started
clakta.initiateCheckout({
orderId: "1001",
totalPrice: 59.98,
currency: "USD",
products: [{ id: "42", name: "Tee", price: 29.99, quantity: 2 }],
customer: { email: "[email protected]" },
})
// Purchase completed
clakta.purchase({
orderId: "1001",
totalPrice: 59.98,
currency: "USD",
paymentMethod: "credit_card",
products: [{ id: "42", name: "Tee", price: 29.99, quantity: 2 }],
customer: { email: "[email protected]" },
// Optional — clkt is read from the URL when you don't pass one
tracking: { utm_source: "facebook", utm_medium: "cpc" },
})
也有 pageViewWithProduct({ id, name, price, currency }) 有关产品详细信息的页面视图。
顺序是确定的,而不是定义的
initiateCheckout 和 purchase 需要 orderId -订单的id在你自己的数据库,和相同的值,你的服务器发送给 订单的API. 没有调用的调用将被丢弃,并发出控制台警告。
这个id是浏览器事件唯一需要正确处理的事情。Clakta将其与服务器发布的命令进行了协调 服务员的命令永远是真相的来源 用于状态、总数和内容。两个值得设计的结果:
- 一个访问者在你的感谢页面呈现之前关闭了标签页,这不会给你带来任何损失——服务器端的订单仍然会到达。
- 客户不能发明或修改订单。服务器拥有的字段(
projectId,platform,status(时间戳)在这里根本不被接受。
其余部分是Orders API有效负载的一个小识别子集,使用相同的字段名称,因此双方以相同的方式描述订单:
| 场 | 类型 | 笔记 |
|---|---|---|
orderId | string | number | 必需的。 数字被标准化为字符串。 |
totalPrice | number | 小数。 59.98. |
currency | string | ISO 4217。默认为项目货币。 |
paymentMethod | ClaktaPaymentMethod | credit_card, pix, paypal, apple_pay(订单API enum)。 |
products | { id, name, quantity, price }[] | 产品id被规范化为字符串。 |
customer | { email, phone, name } | 标识符。见下文。 |
tracking | ClaktaTrackingParams | 属性参数。看到 下面. |
customer 是个人资料,所以才会发下去 full_attribution 征得同意后——进来 privacy_friendly 模式中,块完全从负载中删除,同样的方式 identify 这里是no-op。事件本身仍然被记录: orderId 单独就足以调和它。
addToCart 需要相同的 products / totalPrice / currency 但是没有 orderId,因为这个命令还不存在。
归因
initiateCheckout 和 purchase 接受可选的 tracking block -你的服务器发送到订单API的相同的block,所以双方都将订单归为相同的点击:
| 场 | 类型 | 笔记 |
|---|---|---|
clkt | string | Clakta点击令牌。 当省略时从URL解析 -见下文。 |
utm_source | string | 如。 "facebook". |
utm_medium | string | 如。 "cpc". |
utm_campaign | string | 如。 "summer-sale". |
utm_content | string | 如。 "video-a". |
clakta.purchase({
orderId: "1001",
totalPrice: 59.98,
tracking: {
clkt: "meta:facebook:123456:987654:555555", // optional
utm_source: "facebook",
utm_medium: "cpc",
utm_campaign: "summer-sale",
utm_content: "video-a",
},
})
每个字段都是可选的——没有任何字段的订单被记录为未归属的——你传递的任何额外的东西都被保存为元数据。
clkt 是SDK可以自己恢复的一个值,因为它通常不存在:令牌到达广告的登陆URL,当访问者到达结帐时,查询字符串早就消失了。当你省略它时,SDK会寻找 ?clkt= 在当前的URL,然后在URL访问登陆。回退会读取存储状态,所以它适用于 full_attribution 经同意;在 privacy_friendly 模式不涉及存储,只检查当前URL。通过 clkt 您自己(例如,来自您自己的服务器端订单记录),您的值按原样使用。
decorateLemonSqueezyUrl(url)
Lemon Squeezy结账链接可以携带访问者的会话,并且SDK为您添加了它:当有人点击链接到 *.lemonsqueezy.com/checkout/buy/… 或者 /buy/…,它附加了 checkout[custom][clakta_session_id] (和 checkout[custom][clkt] 当访问在点击完成之前带有点击令牌时。Lemon Squeezy将其永久存储在订单上,并将其发送回网络钩子上,因此Clakta将销售归功于制作它的访问者。托管checkout和Lemon.js覆盖按钮都被覆盖了,并且没有添加任何东西到一次性使用中 ?cart= URL或您自己已经设置的键。
您只需要在自己打开的结帐时使用此函数:
LemonSqueezy.Url.Open(
clakta.decorateLemonSqueezyUrl("https://acme.lemonsqueezy.com/buy/abc-123"),
)
而是通过Lemon Squeezy的API构建结帐?传入会话 checkout_data.custom 当你创建它们-它是相同的密钥,这是最可靠的选项,因为它从不依赖于浏览器:
custom: {
clakta_session_id: claktaSessionId
}
URL将原样返回 privacy_friendly 模式和拒绝同意时:这些访问者没有客户端id, Clakta在服务器端派生他们的身份。
decoratePaddleCheckout(options)
划桨结帐将访客的会话带入 customData,并且SDK为您添加了它-两种结账方式都可以打开:
- HTML结帐按钮。 当有人点击带有Paddle的元素时
paddle_button类,则SDK合并clakta_session_id(和clkt(当访问携带点击令牌时)进入其data-custom-data在Paddle.js读取它之前。 Paddle.Checkout.open(). 一旦加载了Paddle.js, SDK就会包装这个方法,所以编程覆盖或内联检出不需要您自己的代码。
这在Paddle上比在其他任何地方都更有价值:Paddle将事务的自定义数据复制到它创建的订阅上,并从那里复制到每次更新上——因此,在结帐时的一次装饰将订阅的整个生命周期属性化。
当你在SDK看不到的地方构建options对象时,你只需要函数本身:
Paddle.Checkout.open(
clakta.decoratePaddleCheckout({
items: [{ priceId: "pri_01gm81eqze2vmmvhpjg13bfeqg", quantity: 1 }],
}),
)
而是通过Paddle的API创建事务?传入会话 custom_data 当你创建它们-它是相同的密钥,这是最可靠的选项,因为它从不依赖于浏览器:
custom_data: {
clakta_session_id: claktaSessionId
}
您自己已经设置的键永远不会被覆盖,并且选项将原样返回 privacy_friendly 模式和拒绝同意时:这些访问者没有客户端id, Clakta在服务器端派生他们的身份。
decorateCaktoUrl(url)
Cakto结帐链接可以携带访问者的会话,SDK为您添加它:当有人点击链接到 pay.cakto.com.br/…,它附加了 ?sck= 使用单击完成之前的会话id。Cakto将这些信息存储在订单中,并在webhook上报告,这样Clakta就把这笔交易归功于完成交易的访问者。
Cakto还在自己的域名中保存cookie的值,并将其应用于随后的购买,因此装饰访问者点击的链接就足够了——他们可以在结账时移动,仍然可以获得积分。
你只需要在SDK看不到的地方构建URL的函数本身,比如服务器端重定向或路由器链接:
window.location.href = clakta.decorateCaktoUrl(
"https://pay.cakto.com.br/AA58c2n",
)
sck 是唯一的领域Cakto提供,所以不像柠檬挤压和划桨的点击令牌不骑-它已经记录在会话服务器端。Cakto的另一个参数, src,它被故意单独放置:它永远不会到达webhook,所以在践踏你可能正在使用的值时,对它进行写入对Clakta是不可见的。一个 sck 您自己设置的URL永远不会被覆盖,并且返回的URL也不会被更改 privacy_friendly 模式和拒绝同意时:这些访问者没有客户端id, Clakta在服务器端派生他们的身份。
decorateKiwifyUrl(url)
kiwiify结帐链接可以携带访问者的会话,SDK为您添加它:当有人点击链接到 pay.kiwify.com.br/… (或 pay.kiwify.com/…),它是追加的 ?sck= 使用单击完成之前的会话id。kiwiify将其存储在订单中,并将其报告给内部 TrackingParameters 所以Clakta把这笔交易归功于制作它的访问者。
你只需要在SDK看不到的地方构建URL的函数本身,比如服务器端重定向或路由器链接:
window.location.href = clakta.decorateKiwifyUrl(
"https://pay.kiwify.com.br/dF32ZQ8",
)
sck 是kiwiify提供的唯一字段,因此与Cakto一样,点击令牌不会跟随-它已经记录在会话服务器端。kiwiify的另一个自由模式, src,被刻意保留:商家用它作为自己的来源标签,并在kiwiify自己的报告中阅读它。一个 sck 您自己设置的URL永远不会被覆盖,并且返回的URL也不会被更改 privacy_friendly 模式和拒绝同意时:这些访问者没有客户端id, Clakta在服务器端派生他们的身份。
在kiwiify自己的结帐主机上进行装饰匹配,因此从您的自定义域提供的结帐将原样返回-追加 sck 你自己在这种情况下,使用 clakta.getSessionId().
decorateHotmartUrl(url)
Hotmart结帐链接可以携带访问者的会话,SDK为您添加它:当有人点击链接到 pay.hotmart.com/…,它附加了 ?sck= 使用单击完成之前的会话id。Hotmart将这些信息存储起来,并在订单中报告,因此Clakta将这笔交易归功于完成交易的访客。
热链接也被装饰。 go.hotmart.com/… 大多数生产商和附属公司实际上是共享的域名,并且它将收到的跟踪参数转发到它登陆的结帐处-因此,从共享热链接开始的销售被归为相同的方式 pay. 是多少。
你只需要在SDK看不到的地方构建URL的函数本身,比如服务器端重定向或路由器链接:
window.location.href = clakta.decorateHotmartUrl(
"https://pay.hotmart.com/P12345678X",
)
sck 是Clakta写入的唯一字段,因此对于Cakto和kiwiify来说,点击令牌不会跟着走——它已经在会话服务器端记录下来了。Hotmart的其他参数被刻意保留: src 你是否已经在Hotmart自己的报告中使用了源标签 xcod 包含Hotmart的会员热链接代码,因此覆盖它可能会使会员失去销售佣金。一个 sck 您自己设置的URL永远不会被覆盖,并且返回的URL也不会被更改 privacy_friendly 模式和拒绝同意时:这些访问者没有客户端id, Clakta在服务器端派生他们的身份。
在Hotmart自己的主机上进行装饰匹配,因此从您的自定义域名提供的结帐服务将原样返回-追加 sck 你自己在这种情况下,使用 clakta.getSessionId().
consent.update(enabled) / getConsent()
看到 同意.
打印稿
包自带自己的类型——不 @types/* 需要的。
import clakta, {
type ClaktaCartDetails,
type ClaktaOptions,
type ClaktaOrderCustomer,
type ClaktaOrderDetails,
type ClaktaPaymentMethod,
type ClaktaProduct,
type ClaktaTrackingParams,
type CustomerData,
type ResolvedConfig,
type TrackingMode,
} from "@clakta/javascript"
服务器端呈现
每个入口点都是仅浏览器和无操作安全的 window 未定义,因此在SSR构建中导入包不会抛出。在服务器上进行的调用什么也不做。
链接
跟踪运输回归检验
从存储库根目录运行 pnpm dlx [email protected] --test packages/javascript/test/ingestion.test.ts. 这将检查fetch/sendBeacon路由、未更改的有效负载会话标识符、自定义主机和Stripe checkout隔离。