Loading...
Loading...
Compare original and translation side by side
┌─────────────────────────────────────────────────────────────────────┐
│ Your Code │
│ │
│ 1. Define parameters with defaults │
│ 2. Use the resolved values │
│ 3. Track events on conversion │
└─────────────────────────────────────────────────────────────────────┘
▲
│ (hidden from you)
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Traffical │
│ │
│ • Layers & policies for mutual exclusivity │
│ • Bucket assignment & deterministic hashing │
│ • Thompson Sampling & contextual bandits │
│ • Statistical analysis & optimization │
└─────────────────────────────────────────────────────────────────────┘useTraffical()decide()trackDecisions: truetrack()┌─────────────────────────────────────────────────────────────────────┐
│ 你的代码 │
│ │
│ 1. 定义带默认值的参数 │
│ 2. 使用解析后的参数值 │
│ 3. 在转化节点跟踪事件 │
└─────────────────────────────────────────────────────────────────────┘
▲
│ (对你透明的底层逻辑)
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Traffical │
│ │
│ • 用于互斥性的层级与策略机制 │
│ • 用户分组与确定性哈希算法 │
│ • 汤普森采样与上下文多臂老虎机算法 │
│ • 统计分析与自动优化 │
└─────────────────────────────────────────────────────────────────────┘useTraffical()decide()trackDecisions: truetrack()| Scenario | Action |
|---|---|
| Adding a new feature | Wrap in feature flag for gradual rollout |
| Changing existing UI | A/B test against current implementation |
| Modifying conversion paths | Experiment with success metrics |
| Updating algorithms/logic | Test impact before full rollout |
| Anything affecting revenue | Always experiment first |
| 场景 | 操作 |
|---|---|
| 新增功能 | 用功能标志包裹,逐步推出 |
| 修改现有UI | 与当前实现进行A/B测试 |
| 调整转化路径 | 针对成功指标进行实验 |
| 更新算法/逻辑 | 全面推出前测试影响 |
| 任何影响营收的变更 | 务必先进行实验 |
npx @traffical/cli init --api-key <management-key> --framework <name> --yes.traffical/--framework--yes.traffical/config.yamlnpx @traffical/cli pushnpx @traffical/cli statusnpx @traffical/cli init --api-key <management-key> --framework <name> --yes.traffical/--framework--yes.traffical/config.yamlnpx @traffical/cli pushnpx @traffical/cli status@traffical/clinpxnpx @traffical/cli <command>npm install -g @traffical/cli
traffical <command>@traffical/clinpxnpx @traffical/cli <command>npm install -g @traffical/cli
traffical <command>.traffical/traffical.yaml.traffical/traffical.yaml.traffical/Important: Theflag requires a real Management Key or Full Access key. Never fabricate or guess API keys. If no key is available in environment variables (--api-key) orTRAFFICAL_API_KEY, ask the user to provide one from https://app.traffical.io/settings/api-keys.~/.trafficalrc
undefined.traffical/重要提示:标志需要有效的管理密钥或全权限密钥。请勿伪造或猜测API密钥。如果环境变量(--api-key)或TRAFFICAL_API_KEY中没有可用密钥,请让用户从https://app.traffical.io/settings/api-keys获取。~/.trafficalrc
undefined
**Available flags for `init`:**
| Flag | Description |
|------|-------------|
| `--api-key <key>` | Management or Full Access key (falls back to `TRAFFICAL_API_KEY` env var or `~/.trafficalrc`) |
| `--framework <name>` | Skip framework detection. Values: `react`, `nextjs`, `svelte`, `sveltekit`, `vue`, `nuxt`, `node` |
| `--project <id>` | Use a specific project (skips project selection prompt, useful with org-scoped keys) |
| `-y, --yes` | Auto-accept all detected defaults — no interactive prompts |
| `--no-sdk-key` | Skip automatic SDK key creation |
> **For AI agents:** Always pass `--framework` and `--yes` to avoid interactive prompts that will hang in non-TTY environments.
This creates:
The CLI auto-detects your framework (React, Next.js, Svelte, SvelteKit, Vue, Nuxt, Node.js) and generates appropriate templates. Existing synced parameters and events are imported into `config.yaml` automatically.
**After init**, add `TRAFFICAL_API_KEY` from `.traffical/.env` to your project's `.env` or hosting environment for runtime SDK use. The auto-generated key has `sdk:read` and `sdk:write` scopes — just enough for parameter resolution and event tracking.
**`init`命令可用标志:**
| 标志 | 描述 |
|------|-------------|
| `--api-key <key>` | 管理密钥或全权限密钥(优先从环境变量`TRAFFICAL_API_KEY`或`~/.trafficalrc`读取) |
| `--framework <name>` | 跳过框架检测。可选值:`react`, `nextjs`, `svelte`, `sveltekit`, `vue`, `nuxt`, `node` |
| `--project <id>` | 使用指定项目(跳过项目选择提示,适用于组织级密钥) |
| `-y, --yes` | 自动接受所有检测到的默认值——无交互式提示 |
| `--no-sdk-key` | 跳过自动创建SDK密钥 |
> **针对AI Agent:**请始终传入`--framework`和`--yes`,避免在非TTY环境中出现交互式提示导致进程挂起。
初始化后会创建以下文件:
CLI会自动检测你的框架(React、Next.js、Svelte、SvelteKit、Vue、Nuxt、Node.js)并生成对应的模板。已同步的参数和事件会自动导入到`config.yaml`中。
**初始化完成后**,将`.traffical/.env`中的`TRAFFICAL_API_KEY`添加到项目的`.env`或托管环境变量中,供运行时SDK使用。自动生成的密钥拥有`sdk:read`和`sdk:write`权限——刚好满足参数解析和事件跟踪的需求。undefinedundefined
**Always run `npx @traffical/cli push` after modifying `.traffical/config.yaml`.** This syncs your changes to the platform and prevents drift.
**修改`.traffical/config.yaml`后,请务必运行`npx @traffical/cli push`**。这会将你的变更同步到平台,避免配置漂移。| Key Type | Prefix | Purpose | Scopes |
|---|---|---|---|
| SDK Key | | Runtime SDKs — fetch config, send events | |
| Management Key | | CLI, CI/CD — create/modify entities, push/pull/sync | |
| Full Access Key | | Administrative — all operations | |
| 密钥类型 | 前缀 | 用途 | 权限范围 |
|---|---|---|---|
| SDK密钥 | | 运行时SDK——获取配置、发送事件 | |
| 管理密钥 | | CLI、CI/CD——创建/修改实体、推送/拉取/同步 | |
| 全权限密钥 | | 管理员操作——所有权限 | |
--api-key~/.trafficalrc.traffical/.env.traffical/.gitignore.env~/.trafficalrc.traffical/.env--api-key~/.trafficalrc.traffical/.env.traffical/.gitignore.env~/.trafficalrc.traffical/.envinit.traffical/.envinit.traffical/.env
Copy this value to your project's `.env` or hosting environment variables for your SDK to use at runtime.
请将该值复制到项目的`.env`或托管环境变量中,供SDK运行时使用。traffical init.traffical/config.yamlproject.idproject.orgIdenv"production".traffical/.envTRAFFICAL_API_KEYtraffical init.traffical/config.yamlproject.idproject.orgIdenv"production".traffical/.envTRAFFICAL_API_KEY| Package | Use case |
|---|---|
| React and Next.js apps |
| Svelte and SvelteKit apps |
| Server-side Node.js (Express, Fastify, etc.) |
| Any browser environment |
undefined| 包名 | 适用场景 |
|---|---|
| React和Next.js应用 |
| Svelte和SvelteKit应用 |
| 服务端Node.js(Express、Fastify等) |
| 任何浏览器环境 |
undefinedundefinedundefinedimport { TrafficalProvider } from "@traffical/react";
function App() {
return (
<TrafficalProvider
config={{
orgId: "org_xxx",
projectId: "proj_xxx",
env: "production",
apiKey: "pk_live_your_public_key",
}}
// Optional: provide unitKeyFn for logged-in users
// unitKeyFn: () => currentUser.id,
>
<MyApp />
</TrafficalProvider>
);
}import { useTraffical } from "@traffical/react";
function CheckoutButton() {
const { params, track } = useTraffical({
defaults: {
"checkout.button.color": "#1E6EFB",
"checkout.button.label": "Buy now",
},
});
return (
<button
style={{ backgroundColor: params["checkout.button.color"] }}
onClick={() => track("checkout_click")}
>
{params["checkout.button.label"]}
</button>
);
}import { TrafficalProvider } from "@traffical/react";
function App() {
return (
<TrafficalProvider
config={{
orgId: "org_xxx",
projectId: "proj_xxx",
env: "production",
apiKey: "pk_live_your_public_key",
}}
// 可选:为已登录用户提供unitKeyFn
// unitKeyFn: () => currentUser.id,
>
<MyApp />
</TrafficalProvider>
);
}import { useTraffical } from "@traffical/react";
function CheckoutButton() {
const { params, track } = useTraffical({
defaults: {
"checkout.button.color": "#1E6EFB",
"checkout.button.label": "立即购买",
},
});
return (
<button
style={{ backgroundColor: params["checkout.button.color"] }}
onClick={() => track("checkout_click")}
>
{params["checkout.button.label"]}
</button>
);
}<!-- src/routes/+layout.svelte -->
<script>
import { setTrafficalContext } from "@traffical/svelte";
setTrafficalContext({
orgId: "org_xxx",
projectId: "proj_xxx",
env: "production",
apiKey: "pk_live_your_public_key",
context: { userId: data.user?.id ?? "anonymous" },
});
</script>
<slot />paramstrack$<script>
import { getTraffical } from "@traffical/svelte";
const { params, track } = getTraffical({
defaults: {
"checkout.button.color": "#1E6EFB",
"checkout.button.label": "Buy now",
},
});
</script>
<button
style="background-color: {$params['checkout.button.color']}"
on:click={() => $track("checkout_click")}
>
{$params["checkout.button.label"]}
</button><!-- src/routes/+layout.svelte -->
<script>
import { setTrafficalContext } from "@traffical/svelte";
setTrafficalContext({
orgId: "org_xxx",
projectId: "proj_xxx",
env: "production",
apiKey: "pk_live_your_public_key",
context: { userId: data.user?.id ?? "anonymous" },
});
</script>
<slot />paramstrack$<script>
import { getTraffical } from "@traffical/svelte";
const { params, track } = getTraffical({
defaults: {
"checkout.button.color": "#1E6EFB",
"checkout.button.label": "立即购买",
},
});
</script>
<button
style="background-color: {$params['checkout.button.color']}"
on:click={() => $track("checkout_click")}
>
{$params["checkout.button.label"]}
</button>import { createTrafficalClient } from "@traffical/node";
const traffical = await createTrafficalClient({
orgId: "org_xxx", // from .traffical/config.yaml
projectId: "proj_xxx", // from .traffical/config.yaml
env: "production",
apiKey: process.env.TRAFFICAL_API_KEY!, // from .traffical/.env
});
// Resolve parameters (synchronous, from cached bundle)
const params = traffical.getParams({
context: { userId: "user_789", locale: "en-US" },
defaults: {
"checkout.button.color": "#1E6EFB",
"pricing.discount_pct": 0,
},
});
// Track events (value goes in properties, unitKey in options)
traffical.track("purchase", { value: 49.99 }, { unitKey: "user_789" });import { createTrafficalClient } from "@traffical/node";
const traffical = await createTrafficalClient({
orgId: "org_xxx", // 来自.traffical/config.yaml
projectId: "proj_xxx", // 来自.traffical/config.yaml
env: "production",
apiKey: process.env.TRAFFICAL_API_KEY!, // 来自.traffical/.env
});
// 解析参数(同步操作,从缓存读取)
const params = traffical.getParams({
context: { userId: "user_789", locale: "en-US" },
defaults: {
"checkout.button.color": "#1E6EFB",
"pricing.discount_pct": 0,
},
});
// 跟踪事件(值放在properties中,unitKey放在options中)
traffical.track("purchase", { value: 49.99 }, { unitKey: "user_789" });@traffical/nodeimport { createTrafficalClient } from "@traffical/node";
const traffical = await createTrafficalClient({
orgId: "org_xxx", // from .traffical/config.yaml
projectId: "proj_xxx", // from .traffical/config.yaml
env: "production",
apiKey: process.env.TRAFFICAL_API_KEY!,
});
const params = traffical.getParams({
context: { unitKey: "batch-job" },
defaults: {
"feature.new_algorithm": false,
"processing.batch_size": 100,
},
});
if (params["feature.new_algorithm"]) {
// Use new algorithm
}@traffical/nodeimport { createTrafficalClient } from "@traffical/node";
const traffical = await createTrafficalClient({
orgId: "org_xxx", // 来自.traffical/config.yaml
projectId: "proj_xxx", // 来自.traffical/config.yaml
env: "production",
apiKey: process.env.TRAFFICAL_API_KEY!,
});
const params = traffical.getParams({
context: { unitKey: "batch-job" },
defaults: {
"feature.new_algorithm": false,
"processing.batch_size": 100,
},
});
if (params["feature.new_algorithm"]) {
// 使用新算法
}track()track(event, properties?)decisionIdunitKeytrack("purchase", { value: 49.99 })track(event, properties?, options?)unitKeytraffical.track("purchase", { value: 49.99 }, { unitKey: userId })decisionIdtrack()track(event, properties?)decisionIdunitKeytrack("purchase", { value: 49.99 })track(event, properties?, options?)unitKeytraffical.track("purchase", { value: 49.99 }, { unitKey: userId })decisionId.traffical/config.yamltraffical.yamlversion: "1.0"
project:
id: proj_xxx
orgId: org_xxx
parameters:
checkout.button.color:
type: string
default: "#1E6EFB"
description: Primary CTA button color
checkout.show_trust_badges:
type: boolean
default: false
pricing.discount_pct:
type: number
default: 0
events:
purchase:
valueType: currency
unit: USD
description: User completes a purchase
add_to_cart:
valueType: count
description: User adds item to cart.traffical/config.yamltraffical.yamlversion: "1.0"
project:
id: proj_xxx
orgId: org_xxx
parameters:
checkout.button.color:
type: string
default: "#1E6EFB"
description: 主CTA按钮颜色
checkout.show_trust_badges:
type: boolean
default: false
pricing.discount_pct:
type: number
default: 0
events:
purchase:
valueType: currency
unit: USD
description: 用户完成购买
add_to_cart:
valueType: count
description: 用户将商品加入购物车| Type | Use case |
|---|---|
| Colors, labels, URLs, template names |
| Prices, percentages, thresholds, timeouts |
| Feature flags, simple toggles |
| Structured config (multiple related settings) |
| 类型 | 适用场景 |
|---|---|
| 颜色、标签、URL、模板名称 |
| 价格、百分比、阈值、超时时间 |
| 功能标志、简单开关 |
| 结构化配置(多个相关设置) |
| Value Type | Use case |
|---|---|
| Monetary values (revenue, order value) |
| Numeric counts (clicks, items, views) |
| Percentages or ratios |
| Binary events (happened or not) |
| 值类型 | 适用场景 |
|---|---|
| 货币价值(收入、订单金额) |
| 数值计数(点击、商品数量、浏览量) |
| 百分比或比率 |
| 二元事件(发生或未发生) |
events:.traffical/config.yamlevents:
purchase:
valueType: currency
unit: USD
description: User completes a purchase
signup:
valueType: boolean
description: User creates an account
page_view:
valueType: count
description: User views a pagevalueTypecurrencycountratebooleanunitUSDEURdescriptionnpx @traffical/cli pushtrack().traffical/config.yamlevents:events:
purchase:
valueType: currency
unit: USD
description: 用户完成购买
signup:
valueType: boolean
description: 用户创建账户
page_view:
valueType: count
description: 用户浏览页面valueTypecurrencycountratebooleanunitUSDEURdescriptionnpx @traffical/cli pushtrack()parameters:
bookmarks.max_stored:
type: number
default: 100
namespace: bookmarks # optional organizational grouping
description: Maximum bookmarks per user"main"npx @traffical/cli pullinitnamespace: <name>bookmarks.max_storedbookmarksparameters:
bookmarks.max_stored:
type: number
default: 100
namespace: bookmarks # 可选的组织分组
description: 用户可存储的最大书签数量mainnpx @traffical/cli pullnamespace: <name>bookmarks.max_storedbookmarkscategory.subcategory.name| Category | Examples | Use case |
|---|---|---|
| | Feature flags (boolean) |
| | Visual variations |
| | Pricing experiments |
| | Copywriting tests |
| | Explicit variant names |
category.subcategory.name| 分类 | 示例 | 适用场景 |
|---|---|---|
| | 功能标志(布尔类型) |
| | 视觉变体 |
| | 定价实验 |
| | 文案测试 |
| | 显式变体名称 |
npx @traffical/cli pushnpx @traffical/cli status.traffical/config.yamltraffical.yamlnpx @traffical/cli status.traffical/config.yamlnpx @traffical/cli pushconfig.yamlgetParams()useTraffical()track()useTraffical()getTraffical()getParams()category.subcategory.namenpx @traffical/cli pushnpx @traffical/cli status.traffical/config.yamltraffical.yamlnpx @traffical/cli status.traffical/config.yamlnpx @traffical/cli pushconfig.yamlgetParams()useTraffical()track()useTraffical()getTraffical()getParams()category.subcategory.name