@ coframe/ sdk
以AI的动力优化和个性化将你的UX带入生命.
Coframe通过实验,瞄准,反闪克渲染,分析回调和转换跟踪,帮助您个性化和优化您的站点.
此套件暴露出三个切入点:
@coframe/sdk浏览器运行时间@coframe/sdk/server用于 SSR 和边缘预选@coframe/sdk/react用于反应应用程序
安装
npm install @coframe/sdk
如果您使用 React 输入点, 请同时安装 React :
npm install react@">=17"
快开始
浏览器
import { init } from '@coframe/sdk'
await init({
config: {
projectId: 'your-project-id',
},
})
init() 接受 config 和可选 projectData,因此 npm 消费者不需要手动填充 window.CFQ 先说.
运行时间结束点覆盖
私人- CDN 集成可以覆盖浏览器 SDK 的项目和摄取 结束点 :
await init({
config: {
projectId: 'your-project-id',
projectUrl: 'https://cdn.example.com/coframe/project.json',
ingestUrl: 'https://www.example.com/ingest/v2',
replayScriptUrl: 'https://www.example.com/replay/latest.js',
enableDebug: false,
},
})
projectUrl 必须返回原始,完整 Project JSON对象. ingestUrl
替换摄入基址( E)https://ingest.app.coframe.com/ingest/v2; 计 数
SDK 仍然附加类别和工程路径,所以信标会前往
<ingestUrl>/batched_events/<projectId>/, (中文(简体) ), <ingestUrl>/batched_monitoring/<projectId>/, (中文(简体) ),
<ingestUrl>/session_result/,以及 <ingestUrl>/identify/<projectId>/。代理服务器
只需转发 <ingestUrl>/* 改为 https://ingest.app.coframe.com/ingest/v2/*
路径不变。 两种覆盖都是可选的,并保留编译
省略时的 Coframe 结束点 .
replayScriptUrl 替换会话重放记录器脚本 URL。 代理必须
转交 <edge>/replay/latest.js 不变.
配置( O) projectUrl 或者说 ingestUrl 使用 CMAB 实验
确定本地任务而无需调用边缘任务 API .
当浏览器必须避免SDK编译时配置全部三个覆盖
Coframe项目,完全摄入并重放脚本端点. 调试工具
仍由 enableDebug。 。 。 .
URL 控制
Npm 条目使用与脚本标签和边缘相同的浏览器 URL 控制 设施:
cf_disable跳过初始化并显示任何反闪克状态.coframe_variant_id预览一个或多个逗号分隔的变体ID。 添加rollouts在名单中,请在推出的获奖者中先应用 生产访问者会得到.coframe_should_send_events=true允许预览期间的事件进行测试.
默认允许调试工具 。 预览链接( E)coframe_variant_id 与
cf_preview=true)将当前标签的选定变体保持为您
导航; 关闭 保持导航 预览会话工具中的
停下来 设定 enableDebug: false 来防止 URL 或保存会话状态
加载启动器(然后一个预览链接仅适用于自己的页面).
对于 SSR ,通过完整的请求 URL,包括其查询字符串,作为
currentUrl。这是对查询敏感的选择和允许
getProjectData() 至短路之前的任何请求 cf_disable 实值
现相.
反应
import { CoframeProvider } from '@coframe/sdk/react'
import type { CoframeConfig } from '@coframe/sdk'
const projectConfig: CoframeConfig = {
projectId: 'your-project-id',
}
export default function App({ children }) {
return (
<CoframeProvider projectConfig={projectConfig}>
{children}
</CoframeProvider>
)
}
在您的应用程序根部挂载供应商一次。 它在挂载上初始化了SDK,使治疗状态能够提供给儿童成分. 运行时命令和 SDK 命令 导航观察者在不重挂的情况下处理后续的页面修改.
服务器预选
import { getProjectData } from '@coframe/sdk/server'
const serverData = await getProjectData({
projectId: 'your-project-id',
currentUrl: request.url,
headers: request.headers,
})
const projectData = serverData?.project
? {
project: serverData.project,
personalizationHeaders: serverData.personalizationHeaders,
}
: undefined
过 projectData 输入 <CoframeProvider> 以避免客户端额外项目在第一颜料上取取并个性化.
服务器侧任务
使用 getExperimentAssignment() 当服务器必须知道一个实验
在提供或调用上游服务之前的变体。 边缘执行全部
任务; 软件包永远不会回到本地的桶上 .
import {
generateUserToken,
getExperimentAssignment,
} from '@coframe/sdk/server'
// Next.js `request.cookies.get()` returns `{ name, value }`; other runtimes
// return the string. Either way `userToken` must be the string value.
const existingToken = request.cookies.get('coframe.user.token')?.value
const userToken = existingToken ?? generateUserToken()
if (!existingToken) {
// Do not set `httpOnly`: the browser SDK reads this cookie to reuse the
// same identity. An HttpOnly token makes the browser generate a new one and
// bucket differently, with no error.
response.cookies.set('coframe.user.token', userToken, {
path: '/',
secure: true,
sameSite: 'lax',
maxAge: 400 * 24 * 60 * 60,
})
}
const assignment = await getExperimentAssignment({
projectId: 'your-project-id',
experimentId: 'your-experiment-id',
userToken,
currentUrl: request.url,
headers: request.headers,
})
const upstreamVersion =
assignment?.variant?.slug === 'variant-2' ? 'v2' : 'v1'
软件包从请求头的允许列表中获取访问者的背景 .
明确 userAgent, (中文(简体) ), languages, (中文(简体) ), browserPlatform, (中文(简体) ), country, (中文(简体) ), region, (中文(简体) ),
city, (中文(简体) ), device, (中文(简体) ), botScore, (中文(简体) ), verifiedBotCategory, (中文(简体) ), clientIp, (中文(简体) ),
userVisitCount,以及 userContext 选项将超过衍生值。 仅
路径 cookie 转发给 Edge; 授权和应用程序 cookie 为
未转发. clientIp 仅用于现有的块列表目标.
地理 设备 机器人分数 和客户端 IP 从 cf-* 请求
头. 云飞又添了 cf-ipcountry 财务报告和审定财务报表 cf-connecting-ip 改为每个
- 申请到达原籍; cf-region-code 财务报告和审定财务报表 cf-ipcity 需要帮助
"增加访客定位头" 管理变形, cf-device-type 需求
"按设备类型分类",以及 cf-bot-score 需要装瓶管理加a
变相规则。 如果你的服务器不在Cloudflare后面,或者一个信头不在
启用时,该数值缺失: unknown国家
观众从不匹配,设备会倒回用户代理. 过
country, (中文(简体) ), region, (中文(简体) ), city,以及 device 明确在这种情况下
不论你的堆积物来源如何 价值逐字传送
使用Cloudflare的拼写: country 这是
大写 ISO 3166-1 α-2 代码 (US没有 us, (中文(简体) ), region iSO 3166-2 标准
分区代码( 4)CA),以及 device 一个 desktop, (中文(简体) ), mobile, (中文(简体) ), tablet。 。 。 .
获得结果后,将其项目快照传递给提供者. 这个 浏览器读取相同的标准符号 cookie并运行它现有的任务 流则不再获取项目数据.
<CoframeProvider
projectConfig={{ projectId: 'your-project-id' }}
projectData={assignment?.projectData}
>
{children}
</CoframeProvider>
assignment 实值 undefined 当呼叫失败时(见下文),请读
projectData 并在此决定浏览器是否可以
自行初始化.
generateUserToken() 可用时使用 Web Crypto 并返回到
在没有Web Crypto的服务器运行时间中的非加密UUID生成器。 这个
符号是任务身份,而不是认证证书。 还是这样
稳定到其饼干被取出、过期或被替换.
单独访问计数使用SDK现有的两小时访问边界. 这个
包只读取浏览器 SDK 所写的访问 cookie(coframe.cvc, (中文(简体) ),
coframe.lastVisitTime)并且从未设置它们,所以没有浏览器 SDK 运行
经同意后,计数为1 returning 观众不匹配.
结果是其中之一 variant 或者说 variant: null 结构化
理由(experiment_not_found· ; not_assigned,这也涵盖一个访客
在试验或整个项目中被搁置
浏览器中的默认体验; unsupported_experiment_type 页:1
CMAB目标; preview_active 对于 URL 预览; 更新边缘可能添加理由,
所以把任何你不知道的原因都当作"无变体". 两种形式包括准确的 projectData 边缘使用的快照,所以
浏览器可以从该快照上初始化. 快照还载有
将Edge所使用的语言、平台和访问计数值正常化。 浏览器
仅用于初始任务,并恢复正常
用于后期SPA导航的浏览器出自上下文. 在所有没有
变量,使用默认的上游体验.
函数返回 undefined 用于运输、超时(timeoutMs, (中文(简体) ),
默认 1500 ms),边缘,或响应验证失败,以及何时
currentUrl 携带 cf_disable明确处理该状态。 无效的选项是
编程出错并扔出: 一个空 projectId, (中文(简体) ), experimentId 或者说
userToken页:1 currentUrl 这不是绝对的 URL( 执行并快速)
req.url 是路径, 先建立完整 URL ), 超出范围 languages, (中文(简体) ),
device, (中文(简体) ), botScore, (中文(简体) ), timeoutMs 财务报告和审定财务报表 userVisitCount 值,任意字符串
选项超过其限制( URL 有4096个字符, 用户有2048个字符)
代理,200块 projectId, 512为 experimentId 财务报告和审定财务报表 userToken),或 a
userContext 序列化为4096字节(userContext is too large) (中文(简体) ). 从
请求头被夹住 。 保存服务器/浏览器
响应的一致性, 不要让浏览器独立获取工程
数据,并在服务器倒回默认状态后指定一个实验.
接受可能不匹配的应用程序可能会初始化
浏览器通常作为其已打开的失败策略 .
边缘无法评估的
服务器任务运行与浏览器相同的确定性逻辑,其中 同样的,相同的项目快照, 和相同的访客背景。 这个 然后浏览器到达同一个桶,因为每个输入都是相同的. 五个 输入类型只存在于页面中,因此Edge无法评价它们:
- JavaScript 目标. A 类
js_function条件( Custom JavaScript that 读取一个页面值,一个饼干,localStorage,或dataLayer仅运行 在浏览器中,无论是坐在观众席上还是帧的激活上 条件。 边缘视之为不相配.- 如果目标实验本身使用JavaScript受众,结果就是
variant: null有理无据not_assigned。不要使用 JavaScript 受众 在服务器上解析的实验. - 同一框架的实验按顺序评估,第一次匹配 赢了 如果一个 JavaScript 目标实验坐落 超过目标 同一个框架,Edge跳过并指定目标,而浏览器 可以匹配并跳过目标. 保留 JavaScript 目标实验 或放在目标之后.
- 同样的情况也适用于JavaScript目标实验,该实验共享 a 车道 目标,无论它坐在哪里: 车道胜利者来自 和Edge无法分辨是否 一个是可以达到的。 让 JavaScript 目标实验脱离目标 车道.
- 如果目标实验本身使用JavaScript受众,结果就是
- CMAB实验. 目标 CMAB 实验返回
variant: null与 原因unsupported_experiment_type。 。 。 . - URL碎片. 服务器从未看到
#fragment页面URL,以及 浏览器重新评价该快照的全部内容location.href边框 该用途base_url_matches忽略查询和片断,并安全; 精确url条件比较两者,aurl_regex运行与全location.href在浏览器中,通过浏览器将拥有的相同URL, 并避免在 URL 的端点上嵌入正则克克塞斯. - 预览. 预览仅限浏览器使用. A 类
coframe_variant_id網址 参数到达Edge,但已公布的预览有效载荷没有命名 实验的变体属于,所以服务器会回答variant: null与 原因preview_active而浏览器将预览从 返回快照。 预览会话保存到整个导航的预览 工具生活在浏览器中sessionStorage永远不能到达边缘 浏览器丢弃快照并获取自己的工程. 两者都影响 仅预览用户; 提供默认的上游体验 . - 莱恩州. 边缘从
coframe.lanes只有饼干. 在 cookie 同意之前, 浏览器会保留要求localStorage,该 服务器无法看到,而服务器不会坚持边际承诺的主张. 因此,Laned实验同意 一旦浏览器写了饼干, 未经饼干同意的访客不能去.
基于URL的观众条件(base_url_matches),国家,设备,
语言、平台、访问类型、搜索、时间、分配或 userContext
双方的评价相同,机器人隐形也一样。 对于平台,Edge得到的相同
navigator.platform 浏览器报告(a) Linux … 安卓德的绳子,
比如说 Linux armv8l),或采取明确 browserPlatform 选项.
如果应用程序使用自定义身份 cookie,请打电话 setUserToken() 在此之前
浏览器初始化 waitForUserToken: true. 一体化还必须
保持服务器和浏览器之间的访问和车道状态对齐.
特性旗和远程配置
浏览器 特性标记使用已有的公开 projectId 且仅收到
标记 公开。 。 。 . selector 可选; 使用 names 页:1
单个旗帜键和 groups 来评价每一页的标记或
商业区.
import { setUserToken } from '@coframe/sdk'
import {
featureFlags,
getFeatureFlag,
getFeatureFlagPayload,
isFeatureEnabled,
onFeatureFlags,
} from '@coframe/sdk/feature-flags'
setUserToken('customer-123')
await featureFlags.init({
projectId: 'your-project-id',
// Optional: replaces the complete default ingest base, including /ingest/v2.
ingestUrl: 'https://events.example.com/coframe',
selector: {
names: ['checkout-redesign'],
groups: ['homepage_campaigns'],
},
})
onFeatureFlags(() => {
if (isFeatureEnabled('checkout-redesign')) {
showNewCheckout()
}
const content = getFeatureFlagPayload('homepage-content')
const checkoutVariant = getFeatureFlag('checkout-layout')
})
特性旗是一个单独的浏览器入口, 不增加或初始化
主SDK捆绑。 当使用两个客户端时, 特性旗重用最新的
setUserToken() 命令,来自 Coframe 共享命令队列,并随后跟进
身份自动改变.
装入不会延迟 Coframe 页面修改 。 同步获取器返回
undefined 直到有缓存或新评价。 浏览器客户端
总是将最新的成功反应保存在记忆中. 同意前,无
特色标志结果或评价背景持续存在。 经同意
客户端还缓存到 localStorage 5分钟然后按键
sHA-256指纹不透明,来自用户代号和评价
上下文。 如果Edge是暂时的 它会回到那个持续的缓存
无. 打电话 reloadFeatureFlags() 要求进行新的评价
当然.
每个单旗人自动记录 a feature_flag_called 事件
在结果装入后。 这适用于布尔、多变量和远程
配置旗. 该活动包括关键、评估值、有效载荷、版本、,
理由和评价要求元数据。 项目、关键和版本
相应的旗帜定义,而不改变边缘响应。 每个
获取器或钩子访问记录它自己的事件,包括反复读取
同样的结果。 阅读而不记录一个事件,通过 { sendEvent: false }数字 :
const variant = getFeatureFlag('checkout-layout', { sendEvent: false })
跟踪使用独立的特性旗队列,而不初始化
主SDK机车. 它遵循共同同意状态:虽然明确同意
已禁用, 事件会留在内存中, 并在获得同意后发送 。 这个
可选特性旗 ingestUrl 具有与
主 SDK; 客户端附件 /batched_events/<projectId>/。 。 。 .
有效载荷支持任何JSON值可达32 KB. 有效载荷只有在 启用了旗帜。 远程配置使用相同的运输和有效载荷 API和 运行时返回所有用户相同的有效载荷 :
import { getRemoteConfig } from '@coframe/sdk/feature-flags'
const navigation = getRemoteConfig('navigation-config')
多变量标记返回一个稳定的变位键 getFeatureFlag()他们
重量将用户分为确定性桶,每个变体可携带一个
独立可选有效载荷. isFeatureEnabled() 仍然是布尔
方便和回报 true 当指定变体时:
import {
getFeatureFlag,
getFeatureFlagPayload,
isFeatureEnabled,
} from '@coframe/sdk/feature-flags'
const variant = getFeatureFlag('checkout-layout')
const config = getFeatureFlagPayload('checkout-layout')
const enabled = isFeatureEnabled('checkout-layout')
React App可以读取来自现有提供者的评价值:
import {
useFeatureFlag,
useFeatureFlagEnabled,
useFeatureFlagPayload,
useFeatureFlagVariantKey,
} from '@coframe/sdk/react'
function Checkout() {
const enabled = useFeatureFlag('checkout-redesign')
const payload = useFeatureFlagPayload('checkout-redesign')
if (enabled === undefined) return <CheckoutSkeleton />
return enabled ? <NewCheckout config={payload} /> : <OldCheckout />
}
function CheckoutLayout() {
const variant = useFeatureFlagVariantKey('checkout-layout')
const enabled = useFeatureFlagEnabled('checkout-layout')
const payload = useFeatureFlagPayload('checkout-layout')
return <Checkout variant={variant} enabled={enabled} config={payload} />
}
对于服务器和边缘运行时间,使用一个秘密的Feature Flags Server API密钥. 没错
工程范围,可以读取 私营 旗帜,绝对不能包括在
浏览器捆绑或 a NEXT_PUBLIC_* 环境变量. evaluateFlags()
记录由选择器返回的每个旗帜, 而每个单键帮助器
只记录那把钥匙。 重复评价记录了新的事件,即使
结果不变。 两条路径均在不拖延结果的情况下排列跟踪
并接受 sendEvent: false 在不记录事件的情况下进行评估.
单键助手发送密钥过滤请求并失败关闭, 除非
defaultValue 提供。 浏览器和服务器助手都呼叫
/api/v1/flags; 服务器帮助器包括 API 密钥作为 Bearer 证书
答复可包括两个方面: 公开 财务报告和审定财务报表 私营 旗帜 :
import {
evaluateFlags,
flushFeatureFlagEvents,
getFeatureFlag,
getRemoteConfig,
isFeatureEnabled,
} from '@coframe/sdk/server'
const options = {
projectId: 'your-project-id',
apiKey: process.env.COFRAME_FEATURE_FLAGS_SERVER_KEY!,
userToken: user.id,
currentUrl: request.url,
userContext: { plan: user.plan },
}
const checkoutFlags = await evaluateFlags({
...options,
selector: { groups: ['cart_checkout'] },
ingestUrl: 'https://events.example.com/coframe',
})
// evaluateFlags tracks every returned flag without another Edge request.
// Single-key helpers track their requested key automatically.
const checkoutVariant = await getFeatureFlag('checkout-layout', {
...options,
ingestUrl: 'https://events.example.com/coframe',
})
// Useful before a short-lived process exits. Tracking failures are swallowed.
await flushFeatureFlagEvents()
const enabled = await isFeatureEnabled('checkout-redesign', {
...options,
defaultValue: false,
})
const variant = await getFeatureFlag('checkout-layout', options)
const content = await getRemoteConfig('homepage-content', options)
常用反应用法
读取组件中的变体
'use client'
import { useCoframeVariant } from '@coframe/sdk/react'
export function CheckoutPage() {
const variant = useCoframeVariant('checkout_flow_v2')
if (variant === undefined) return <CheckoutSkeleton />
if (variant === 'treatment') return <NewCheckout />
return <OldCheckout />
}
其他钩:
useCoframeTreatments()返回所有治疗或null在飞行中useCoframeTreatment(experimentId)返回一个处理有效载荷
音轨转换
'use client'
import { trackConversion } from '@coframe/sdk'
export function CheckoutButton() {
return (
<button
onClick={() =>
trackConversion({
metricName: 'checkout_complete',
value: 99.95,
})
}
>
Complete checkout
</button>
)
}
分析和日志回调
import { CoframeProvider } from '@coframe/sdk/react'
<CoframeProvider
projectConfig={projectConfig}
onTreatmentAppliedBulkV2={(data) => {
for (const treatment of data) {
analytics.track('Experiment Viewed', treatment)
}
}}
onLog={(payload) => {
console.error('[coframe]', payload.monitoring_type, payload)
}}
>
{children}
</CoframeProvider>
如果您的隐私政策允许在饼干同意前进行治疗分析,请使用
onTreatmentAppliedBulkV2WithoutConsent 换句话说 它有同样的召回
在后来表示同意时,不要再次开火.
外部反应,您也可以从主条目注册回调:
import { onLog, onTreatmentApplied } from '@coframe/sdk'
下个.js / Remix / SSR 注释
getProjectData()用于提供完整请求 URL 和请求头的 SSR 和边缘运行时间.- 在Pages路由器或Remix中,每个请求服务器加载器是最直接的调用地点.
- 在 App 路由器中, 将提供者挂载在一个持久 shell 中, 但是要注意请求 URL 处理
layout.tsx如果您需要查询敏感 SSR 目标. - Npm运行时间揭示出反闪克风格,但不能及早插入来保护初始颜料. 渲染器
antiflickerCSS从getProjectData()在服务器文档头中,或者在应用程序内容之前将等同的静态 CSS 和超时退后.
软件包布局
公布的柏油球只包含 dist/pkg/数字 :
dist/pkg/
├── cf.esm.mjs cf.cjs.js types/index.d.ts ← @coframe/sdk
├── server.esm.mjs server.cjs.js types/server.d.ts ← @coframe/sdk/server
└── react.esm.mjs react.cjs.js types/react.d.ts ← @coframe/sdk/react
类型脚本兼容性
该套件发布打入子路径导出, 用于:
@coframe/sdk@coframe/sdk/server@coframe/sdk/react
如果您的应用程序使用更古老的 TypeScript 模块解析模式,则倾向于移动到:
moduleResolution: "bundler"moduleResolution: "node16"moduleResolution: "nodenext"
现代解析模式处理包子路径导出更可靠.
API 概览
@coframe/sdk
init(options)trackConversion(payload)setConsent(enabled)setUserToken(token)setFeatureFlag(enabled)setPageHydrated()onTreatmentApplied(...)onLog(...)
@coframe/sdk/feature-flags
featureFlags.init(options)featureFlags.setUserToken(userToken)编号 :featureFlags.reset()featureFlags.getUserToken()getFeatureFlag(key)编号 :isFeatureEnabled(key)getFeatureFlagPayload(key)编号 :getRemoteConfig(key)onFeatureFlags(callback)编号 :reloadFeatureFlags()
@coframe/sdk/server
getProjectData(options)getExperimentAssignment(options)generateUserToken()evaluateFlags(options)getFeatureFlag(key, options)编号 :isFeatureEnabled(key, options)getFeatureFlagPayload(key, options)编号 :getRemoteConfig(key, options)flushFeatureFlagEvents()
返回载荷,其中可包括:
projectpersonalizationHeadersantiflickerCSS
@coframe/sdk/react
CoframeProvideruseCoframeTreatments()useCoframeTreatment(experimentId)useCoframeVariant(experimentId)useFeatureFlag(key)编号 :useFeatureFlagVariantKey(key)useFeatureFlagEnabled(key)useFeatureFlagResult(key)编号 :useFeatureFlagPayload(key)