[{"data":1,"prerenderedAt":1458},["ShallowReactive",2],{"navigation_docs":3,"-getting-started-experiments":291,"-getting-started-experiments-surround":1453},[4,10,62,88,241,276],{"title":5,"path":6,"stem":7,"icon":8,"exact":9},"Introduction","\u002F","0.index","i-lucide-book-open",true,{"title":11,"icon":12,"modifiedAt":13,"path":14,"stem":15,"children":16,"page":12},"Getting Started",false,"2026-04-30T19:15:33.000Z","\u002Fgetting-started","1.getting-started",[17,22,27,32,37,42,47,52,57],{"title":18,"path":19,"stem":20,"icon":21},"Quickstart","\u002Fgetting-started\u002Fquickstart","1.getting-started\u002F1.quickstart","i-lucide-fast-forward",{"title":23,"path":24,"stem":25,"icon":26},"Core Concepts","\u002Fgetting-started\u002Fcore-concepts","1.getting-started\u002F2.core-concepts","i-lucide-workflow",{"title":28,"path":29,"stem":30,"icon":31},"Configs Anatomy","\u002Fgetting-started\u002Fconfigs","1.getting-started\u002F3.configs","i-lucide-file-cog",{"title":33,"path":34,"stem":35,"icon":36},"Architecture","\u002Fgetting-started\u002Farchitecture","1.getting-started\u002F4.architecture","i-lucide-layers",{"title":38,"path":39,"stem":40,"icon":41},"JSON Schema Validation","\u002Fgetting-started\u002Fjson-schema-validation","1.getting-started\u002F5.json-schema-validation","i-lucide-braces",{"title":43,"path":44,"stem":45,"icon":46},"Testing Rules","\u002Fgetting-started\u002Ftesting-targeting-rules","1.getting-started\u002F6.testing-targeting-rules","i-lucide-flask-conical",{"title":48,"path":49,"stem":50,"icon":51},"Experiments","\u002Fgetting-started\u002Fexperiments","1.getting-started\u002F7.experiments","i-lucide-flask-round",{"title":53,"path":54,"stem":55,"icon":56},"Segments","\u002Fgetting-started\u002Fsegments","1.getting-started\u002F8.segments","i-lucide-squares-intersect",{"title":58,"path":59,"stem":60,"icon":61},"Pricing & Billing","\u002Fgetting-started\u002Fpricing-and-billing","1.getting-started\u002F9.pricing-and-billing","i-lucide-credit-card",{"title":63,"modifiedAt":64,"defaultOpen":9,"path":65,"stem":66,"children":67,"page":12},"Monitoring","2026-09-24T23:33:20.000Z","\u002Fmonitoring","2.monitoring",[68,73,78,83],{"title":69,"path":70,"stem":71,"icon":72},"Activity","\u002Fmonitoring\u002Factivity","2.monitoring\u002F1.activity","i-lucide-activity",{"title":74,"path":75,"stem":76,"icon":77},"Lifecycle","\u002Fmonitoring\u002Flifecycle","2.monitoring\u002F2.lifecycle","i-lucide-recycle",{"title":79,"path":80,"stem":81,"icon":82},"Alerts","\u002Fmonitoring\u002Falerts","2.monitoring\u002F3.alerts","i-lucide-bell",{"title":84,"path":85,"stem":86,"icon":87},"Dynamic Detection","\u002Fmonitoring\u002Fdynamic-detection","2.monitoring\u002F4.dynamic-detection","i-lucide-hat-glasses",{"title":89,"modifiedAt":64,"defaultOpen":9,"path":90,"stem":91,"children":92,"page":12},"SDKs","\u002Fsdks","3.sdks",[93,98,119,144,160,191,236],{"title":94,"path":95,"stem":96,"icon":97},"Available SDKs","\u002Fsdks\u002Favailable-sdks","3.sdks\u002F1.available-sdks","i-lucide-list",{"title":99,"modifiedAt":64,"icon":100,"defaultOpen":12,"path":101,"stem":102,"children":103,"page":12},"Browser SDKs","i-lucide-monitor","\u002Fsdks\u002Fbrowser","3.sdks\u002F2.browser",[104,109,114],{"title":105,"path":106,"stem":107,"icon":108},"Javascript","\u002Fsdks\u002Fbrowser\u002Fjavascript","3.sdks\u002F2.browser\u002F1.javascript","cd-logos-javascript",{"title":110,"path":111,"stem":112,"icon":113},"React","\u002Fsdks\u002Fbrowser\u002Freact","3.sdks\u002F2.browser\u002F2.react","cd-logos-react-light",{"title":115,"path":116,"stem":117,"icon":118},"Vue","\u002Fsdks\u002Fbrowser\u002Fvue","3.sdks\u002F2.browser\u002F3.vue","cd-logos-vue",{"title":120,"modifiedAt":64,"icon":121,"defaultOpen":12,"path":122,"stem":123,"children":124,"page":12},"Mobile SDKs","i-lucide-smartphone","\u002Fsdks\u002Fmobile","3.sdks\u002F3.mobile",[125,129,134,139],{"title":126,"path":127,"stem":128,"icon":113},"React Native","\u002Fsdks\u002Fmobile\u002Freact-native","3.sdks\u002F3.mobile\u002F1.react-native",{"title":130,"path":131,"stem":132,"icon":133},"Flutter","\u002Fsdks\u002Fmobile\u002Fflutter","3.sdks\u002F3.mobile\u002F2.flutter","cd-logos-flutter",{"title":135,"path":136,"stem":137,"icon":138},"Swift","\u002Fsdks\u002Fmobile\u002Fswift","3.sdks\u002F3.mobile\u002F3.swift","cd-logos-swift",{"title":140,"path":141,"stem":142,"icon":143},"Android","\u002Fsdks\u002Fmobile\u002Fandroid","3.sdks\u002F3.mobile\u002F4.android","cd-logos-android",{"title":145,"modifiedAt":64,"icon":146,"defaultOpen":12,"path":147,"stem":148,"children":149,"page":12},"Meta-framework SDKs","i-lucide-monitor-smartphone","\u002Fsdks\u002Fmeta","3.sdks\u002F4.meta",[150,155],{"title":151,"path":152,"stem":153,"icon":154},"Next.js","\u002Fsdks\u002Fmeta\u002Fnextjs","3.sdks\u002F4.meta\u002F1.nextjs","cd-logos-nextjs",{"title":156,"path":157,"stem":158,"icon":159},"Nuxt","\u002Fsdks\u002Fmeta\u002Fnuxt","3.sdks\u002F4.meta\u002F2.nuxt","cd-logos-nuxt",{"title":161,"modifiedAt":64,"icon":162,"defaultOpen":12,"path":163,"stem":164,"children":165,"page":12},"Server SDKs","i-lucide-server","\u002Fsdks\u002Fserver","3.sdks\u002F5.server",[166,171,176,181,186],{"title":167,"path":168,"stem":169,"icon":170},"Node.js","\u002Fsdks\u002Fserver\u002Fnode-js","3.sdks\u002F5.server\u002F1.node-js","cd-logos-nodejs",{"title":172,"path":173,"stem":174,"icon":175},"Python","\u002Fsdks\u002Fserver\u002Fpython","3.sdks\u002F5.server\u002F2.python","cd-logos-python",{"title":177,"path":178,"stem":179,"icon":180},"Java","\u002Fsdks\u002Fserver\u002Fjava","3.sdks\u002F5.server\u002F3.java","cd-logos-java",{"title":182,"path":183,"stem":184,"icon":185},".NET","\u002Fsdks\u002Fserver\u002Fdotnet","3.sdks\u002F5.server\u002F4.dotnet","cd-logos-dotnet",{"title":187,"path":188,"stem":189,"icon":190},"Go","\u002Fsdks\u002Fserver\u002Fgo","3.sdks\u002F5.server\u002F5.go","cd-logos-go",{"title":192,"modifiedAt":64,"icon":193,"defaultOpen":12,"path":194,"stem":195,"children":196},"OpenFeature Providers","cd-logos-openfeature","\u002Fsdks\u002Fopenfeature","3.sdks\u002F6.openfeature\u002Findex",[197,199,204,208,212,216,220,224,228,232],{"title":198,"path":194,"stem":195,"icon":193},"Overview",{"title":200,"path":201,"stem":202,"icon":193,"icons":203},"Web","\u002Fsdks\u002Fopenfeature\u002Fweb","3.sdks\u002F6.openfeature\u002F1.web",[193,108],{"title":135,"path":205,"stem":206,"icon":193,"icons":207},"\u002Fsdks\u002Fopenfeature\u002Fswift","3.sdks\u002F6.openfeature\u002F2.swift",[193,138],{"title":140,"path":209,"stem":210,"icon":193,"icons":211},"\u002Fsdks\u002Fopenfeature\u002Fandroid","3.sdks\u002F6.openfeature\u002F3.android",[193,143],{"title":130,"path":213,"stem":214,"icon":193,"icons":215},"\u002Fsdks\u002Fopenfeature\u002Fflutter","3.sdks\u002F6.openfeature\u002F4.flutter",[193,133],{"title":167,"path":217,"stem":218,"icon":193,"icons":219},"\u002Fsdks\u002Fopenfeature\u002Fnode-js","3.sdks\u002F6.openfeature\u002F5.node-js",[193,170],{"title":172,"path":221,"stem":222,"icon":193,"icons":223},"\u002Fsdks\u002Fopenfeature\u002Fpython","3.sdks\u002F6.openfeature\u002F6.python",[193,175],{"title":177,"path":225,"stem":226,"icon":193,"icons":227},"\u002Fsdks\u002Fopenfeature\u002Fjava","3.sdks\u002F6.openfeature\u002F7.java",[193,180],{"title":182,"path":229,"stem":230,"icon":193,"icons":231},"\u002Fsdks\u002Fopenfeature\u002Fdotnet","3.sdks\u002F6.openfeature\u002F8.dotnet",[193,185],{"title":187,"path":233,"stem":234,"icon":193,"icons":235},"\u002Fsdks\u002Fopenfeature\u002Fgo","3.sdks\u002F6.openfeature\u002F9.go",[193,190],{"title":237,"path":238,"stem":239,"icon":240},"Maven Repository","\u002Fsdks\u002Fmaven-repository","3.sdks\u002F7.maven-repository","i-lucide-package",{"title":242,"modifiedAt":64,"defaultOpen":9,"path":243,"stem":244,"children":245,"page":12},"Integrations","\u002Fintegrations","4.integrations",[246,251,256,261,266,271],{"title":247,"path":248,"stem":249,"icon":250},"MCP","\u002Fintegrations\u002Fmcp","4.integrations\u002F1.mcp","cd-logos-mcp",{"title":252,"path":253,"stem":254,"icon":255},"Agent Skills","\u002Fintegrations\u002Fagents","4.integrations\u002F2.agents","i-lucide-bot",{"title":257,"path":258,"stem":259,"icon":260},"CLI","\u002Fintegrations\u002Fcli","4.integrations\u002F3.cli","cd-logos-cli",{"title":262,"path":263,"stem":264,"icon":265},"Terraform","\u002Fintegrations\u002Fterraform","4.integrations\u002F4.terraform","cd-logos-terraform",{"title":267,"path":268,"stem":269,"icon":270},"Admin API","\u002Fintegrations\u002Fadmin-api","4.integrations\u002F5.admin-api","i-lucide-blocks",{"title":272,"path":273,"stem":274,"icon":275},"Webhooks","\u002Fintegrations\u002Fwebhooks","4.integrations\u002F6.webhooks","i-lucide-webhook",{"title":277,"modifiedAt":278,"defaultOpen":9,"path":279,"stem":280,"children":281,"page":12},"Migration Guides","2026-10-16T17:57:49.000Z","\u002Fmigration-guides","5.migration-guides",[282,287],{"title":283,"path":284,"stem":285,"icon":286},"From LaunchDarkly","\u002Fmigration-guides\u002Flaunchdarkly","5.migration-guides\u002F1.launchdarkly","i-lucide-baggage-claim",{"title":288,"path":289,"stem":290,"icon":286},"From Firebase Remote Config","\u002Fmigration-guides\u002Ffirebase-remote-config","5.migration-guides\u002F2.firebase-remote-config",{"id":292,"title":48,"body":293,"description":1443,"extension":1444,"links":1445,"meta":1446,"navigation":1448,"path":49,"seo":1449,"stem":50,"__hash__":1452},"docs\u002F1.getting-started\u002F7.experiments.md",{"type":294,"value":295,"toc":1422},"minimark",[296,300,309,312,320,325,352,359,366,372,375,380,383,587,592,596,606,683,699,703,717,741,747,754,763,770,780,786,790,803,813,817,824,833,839,847,850,862,866,869,934,938,941,945,952,1005,1011,1017,1026,1030,1060,1063,1067,1076,1088,1095,1102,1105,1109,1119,1122,1136,1140,1147,1162,1169,1177,1181,1184,1233,1236,1240,1243,1412,1418],[297,298,299],"p",{},"An experiment is a config whose variations are compared against each other. You split an environment's traffic between the variations, ConfigDirector counts how many contexts each one reached, and once you have decided, you ship the winner to everyone in one step.",[297,301,302,303,308],{},"ConfigDirector counts and you decide: it does not compare the variations or name a winner. The numbers you judge by come from ",[304,305,307],"a",{"href":306},"#compare-the-variations","the events your application tracks, or your analytics tool",".",[297,310,311],{},"Experiments are available on Free and Pay as you go.",[297,313,314,315,319],{},"This guide follows one A\u002FB test from start to finish: ",[316,317,318],"code",{},"checkout-cta-copy",", which compares two labels for a checkout button.",[321,322,324],"h2",{"id":323},"create-the-experiment","Create the experiment",[297,326,327,328,332,333,336,337,340,341,344,345,348,349,308],{},"On the ",[329,330,331],"strong",{},"Configs"," page, click ",[329,334,335],{},"Create config",", enter a key and choose the ",[329,338,339],{},"Experiment"," role. Choose a type (String, Integer, Float or Boolean), then enter each variation's value and a name for it under ",[329,342,343],{},"Variations",". A Boolean experiment needs no entry here: it gets two variations, named ",[316,346,347],{},"Enabled"," and ",[316,350,351],{},"Disabled",[297,353,354],{},[355,356],"img",{"alt":357,"src":358},"The Variations section of the create form, with the variations control and treatment-a","\u002Fimg\u002Fscreenshots\u002Fexperiments-variations.webp",[297,360,361,362,365],{},"The name is how the dashboard, the audit log, the CLI and OpenFeature refer to a variation, so give each one a name. You can rename a variation later on the ",[329,363,364],{},"Settings"," tab, and its counts stay with it.",[297,367,368,371],{},[329,369,370],{},"Default variation"," sets the default targeting rule value every environment starts with, which is what an environment serves until you split its traffic. It is usually your control.",[297,373,374],{},"Creating an experiment takes the developer role or higher.",[376,377,379],"h3",{"id":378},"read-it-in-your-code","Read it in your code",[297,381,382],{},"Your application reads an experiment like any other config. The second argument is the in-code default value, which your application gets when it cannot get a value from ConfigDirector:",[384,385,386,505],"code-group",{},[387,388,394],"pre",{"className":389,"code":390,"filename":391,"language":392,"meta":393,"style":393},"language-ts shiki shiki-themes github-light-high-contrast github-light github-dark","import { createClient } from \"@configdirector\u002Fclient-sdk\";\n\nconst client = createClient(\"YOUR-CLIENT-SDK-KEY\");\nawait client.initialize({ id: \"user-42\" });\n\nconst buttonLabel = client.getValue(\"checkout-cta-copy\", \"Start free trial\");\n","Browser","ts","",[316,395,396,419,425,451,472,477],{"__ignoreMap":393},[397,398,401,405,409,412,416],"span",{"class":399,"line":400},"line",1,[397,402,404],{"class":403},"sLDKn","import",[397,406,408],{"class":407},"sbRM4"," { createClient } ",[397,410,411],{"class":403},"from",[397,413,415],{"class":414},"suztq"," \"@configdirector\u002Fclient-sdk\"",[397,417,418],{"class":407},";\n",[397,420,422],{"class":399,"line":421},2,[397,423,424],{"emptyLinePlaceholder":9},"\n",[397,426,428,431,435,438,442,445,448],{"class":399,"line":427},3,[397,429,430],{"class":403},"const",[397,432,434],{"class":433},"sxMNI"," client",[397,436,437],{"class":403}," =",[397,439,441],{"class":440},"sEIia"," createClient",[397,443,444],{"class":407},"(",[397,446,447],{"class":414},"\"YOUR-CLIENT-SDK-KEY\"",[397,449,450],{"class":407},");\n",[397,452,454,457,460,463,466,469],{"class":399,"line":453},4,[397,455,456],{"class":403},"await",[397,458,459],{"class":407}," client.",[397,461,462],{"class":440},"initialize",[397,464,465],{"class":407},"({ id: ",[397,467,468],{"class":414},"\"user-42\"",[397,470,471],{"class":407}," });\n",[397,473,475],{"class":399,"line":474},5,[397,476,424],{"emptyLinePlaceholder":9},[397,478,480,482,485,487,489,492,494,497,500,503],{"class":399,"line":479},6,[397,481,430],{"class":403},[397,483,484],{"class":433}," buttonLabel",[397,486,437],{"class":403},[397,488,459],{"class":407},[397,490,491],{"class":440},"getValue",[397,493,444],{"class":407},[397,495,496],{"class":414},"\"checkout-cta-copy\"",[397,498,499],{"class":407},", ",[397,501,502],{"class":414},"\"Start free trial\"",[397,504,450],{"class":407},[387,506,509],{"className":389,"code":507,"filename":508,"language":392,"meta":393,"style":393},"import { createClient } from \"@configdirector\u002Fserver-sdk\";\n\nconst client = createClient(\"YOUR-SERVER-SDK-KEY\");\nawait client.initialize();\n\nconst buttonLabel = client.getValue(\"checkout-cta-copy\", \"Start free trial\", { id: \"user-42\" });\n","Server",[316,510,511,524,528,545,556,560],{"__ignoreMap":393},[397,512,513,515,517,519,522],{"class":399,"line":400},[397,514,404],{"class":403},[397,516,408],{"class":407},[397,518,411],{"class":403},[397,520,521],{"class":414}," \"@configdirector\u002Fserver-sdk\"",[397,523,418],{"class":407},[397,525,526],{"class":399,"line":421},[397,527,424],{"emptyLinePlaceholder":9},[397,529,530,532,534,536,538,540,543],{"class":399,"line":427},[397,531,430],{"class":403},[397,533,434],{"class":433},[397,535,437],{"class":403},[397,537,441],{"class":440},[397,539,444],{"class":407},[397,541,542],{"class":414},"\"YOUR-SERVER-SDK-KEY\"",[397,544,450],{"class":407},[397,546,547,549,551,553],{"class":399,"line":453},[397,548,456],{"class":403},[397,550,459],{"class":407},[397,552,462],{"class":440},[397,554,555],{"class":407},"();\n",[397,557,558],{"class":399,"line":474},[397,559,424],{"emptyLinePlaceholder":9},[397,561,562,564,566,568,570,572,574,576,578,580,583,585],{"class":399,"line":479},[397,563,430],{"class":403},[397,565,484],{"class":433},[397,567,437],{"class":403},[397,569,459],{"class":407},[397,571,491],{"class":440},[397,573,444],{"class":407},[397,575,496],{"class":414},[397,577,499],{"class":407},[397,579,502],{"class":414},[397,581,582],{"class":407},", { id: ",[397,584,468],{"class":414},[397,586,471],{"class":407},[297,588,589,591],{},[304,590,94],{"href":95}," lists the page for each SDK.",[376,593,595],{"id":594},"give-every-context-a-stable-identifier","Give every context a stable identifier",[297,597,598,599,602,603,605],{},"ConfigDirector recognizes a context by its context kind and its ",[316,600,601],{},"id",". A context without an ",[316,604,601],{}," is never counted, and what it is served depends on the SDK:",[607,608,609,625],"table",{},[610,611,612],"thead",{},[613,614,615,619,622],"tr",{},[616,617,618],"th",{},"Context",[616,620,621],{},"What it is served",[616,623,624],{},"Counted as an exposure",[626,627,628,642,656,668],"tbody",{},[613,629,630,636,639],{},[631,632,633,634],"td",{},"Has an ",[316,635,601],{},[631,637,638],{},"Its share of the split, the same one every time",[631,640,641],{},"Yes",[613,643,644,650,653],{},[631,645,646,647,649],{},"No ",[316,648,601],{},", in a browser or mobile SDK",[631,651,652],{},"Its share of the split, until the site's data is cleared or the app is uninstalled",[631,654,655],{},"No",[613,657,658,663,666],{},[631,659,646,660,662],{},[316,661,601],{},", in a server SDK",[631,664,665],{},"The default targeting rule value, because it skips the split",[631,667,655],{},[613,669,670,678,681],{},[631,671,633,672,674,675,662],{},[316,673,601],{}," and is marked ",[316,676,677],{},"anonymous",[631,679,680],{},"Its share of the split",[631,682,655],{},[297,684,685,686,688,689,692,693,695,696,698],{},"So to count signed-out visitors, give each one an ",[316,687,601],{}," of your own, such as one you keep in a cookie. Without it, visitors in a browser or mobile app still see the variations, but the ",[329,690,691],{},"Exposures"," card counts none of them. Leave ",[316,694,677],{}," off as well, because an event tracked for a context marked ",[316,697,677],{}," counts for no experiment, in any SDK.",[321,700,702],{"id":701},"split-traffic-in-an-environment","Split traffic in an environment",[297,704,705,706,708,709,712,713,716],{},"An experiment opens on its ",[329,707,339],{}," tab. Pick the environment at the top. Each environment has its own targeting rules, so it runs its own split and keeps its own counts: a split in ",[316,710,711],{},"Test"," is a rehearsal, and the one in ",[316,714,715],{},"Production"," is the experiment.",[718,719,720,732,735],"ol",{},[721,722,723,724,727,728,731],"li",{},"Click ",[329,725,726],{},"Start experiment…"," to open the ",[329,729,730],{},"Targeting rules"," tab with an even percentage rollout drafted under the rules you have. Nothing is saved yet.",[721,733,734],{},"Adjust the shares if you want something other than an even split.",[721,736,723,737,740],{},[329,738,739],{},"Save",". In a live environment, ConfigDirector asks you to confirm.",[297,742,743],{},[355,744],{"alt":745,"src":746},"A 50 \u002F 50 percentage rollout on the Targeting rules tab, with a note that saving starts a run in Production","\u002Fimg\u002Fscreenshots\u002Fexperiments-rollout.webp",[297,748,749,750,753],{},"That save starts a ",[329,751,752],{},"run",", the period during which the environment splits traffic between the variations. There is no other start step, and exposures are counted from that save on. A percentage rollout saved through the Admin API, the CLI, the MCP server or Terraform starts a run the same way. Starting or stopping a run and shipping a variation take the operator role or higher.",[297,755,756,757,308],{},"Only a percentage rollout starts a run. A rule that serves one variation to a country or a segment is targeting: those contexts were not assigned at random, so there is nothing to compare. To see how often each variation is served there, use the ",[304,758,760,762],{"href":759},"\u002Fmonitoring\u002Factivity#the-activity-tab",[329,761,69],{}," tab",[297,764,765,766,769],{},"To run the experiment on part of your traffic, put the split inside a conditional rule, such as one that matches ",[316,767,768],{},"plan is one of pro, team",". An environment has one run at a time, and a run can hold several percentage rollouts, each with its own counts.",[297,771,772,773,775,776,779],{},"While a run is going, saving different shares, or adding or removing a percentage rollout, ends the run and starts a new one, so each run's counts belong to one set of shares. The note next to ",[329,774,739],{}," tells you when a save would do this, and the run that ended is listed as ",[329,777,778],{},"Replaced",". Editing the other rules leaves the run alone.",[297,781,782,783,785],{},"A copied experiment, or one restored from the archive, keeps its split but has no run until you change the split. The ",[329,784,339],{}," tab says so.",[321,787,789],{"id":788},"test-a-context","Test a context",[297,791,792,793,796,797,799,800,308],{},"To check what a context gets, click ",[329,794,795],{},"Test rules"," on the ",[329,798,730],{}," tab and pick an existing context or enter a custom one. The rollout is marked with the bucket the context falls in and the share that bucket belongs to, for example ",[316,801,802],{},"Bucket 55.2 falls inside the 50% share serving Try it free for 14 days (50 to 100)",[297,804,805,806,808,809,812],{},"The same context gets the same bucket in your applications. The tester works on the rules in the editor, saved or not, so you can test a context before you start the run, and testing never counts as an exposure. For a context without an ",[316,807,601],{},", it answers the way a browser or mobile SDK does. ",[304,810,811],{"href":44},"Testing Targeting Rules"," explains the rest.",[321,814,816],{"id":815},"read-the-exposures","Read the exposures",[297,818,819,820,823],{},"An ",[329,821,822],{},"exposure"," means a context was served a variation through the split during the run. A context counts once per variation, however often it evaluates, so the counts tell you how many contexts each variation reached rather than how much traffic it got.",[297,825,826,827,829,830,832],{},"The ",[329,828,691],{}," card on the ",[329,831,339],{}," tab shows a bar for each variation, with the contexts it reached, their share of the total, and the share you configured, drawn as a tick on the bar. It updates hourly, so expect the first counts within about an hour of your applications evaluating the experiment.",[297,834,835],{},[355,836],{"alt":837,"src":838},"The Exposures card, with 1,154 contexts for control and 1,246 for treatment-a, and a note that the split matches the configured shares","\u002Fimg\u002Fscreenshots\u002Fexperiments-exposures.webp",[297,840,841,842,846],{},"Evaluations served by a conditional rule or by the default targeting rule are not exposures. When evaluations are left out because they came from contexts without an identifier, or from ",[304,843,845],{"href":844},"#sdk-versions-that-report-exposures","SDK versions that do not report exposures yet",", lines under the counts say how many.",[297,848,849],{},"A run with several percentage rollouts shows a block for each, headed by its conditions and checked against its own shares.",[297,851,852,853,856,857,861],{},"To find your experiments, choose ",[329,854,855],{},"Role: Experiment"," in the ",[304,858,860],{"href":859},"\u002Fmonitoring\u002Factivity#finding-configs","configs list",". Each one shows its run in the selected environment under its status.",[376,863,865],{"id":864},"the-mismatch-warning","The mismatch warning",[297,867,868],{},"The card checks the split against the shares you configured, which tells you whether you can trust the run:",[607,870,871,884],{},[610,872,873],{},[613,874,875,878,881],{},[616,876,877],{},"The card says",[616,879,880],{},"What it means",[616,882,883],{},"What to do",[626,885,886,899,912],{},[613,887,888,893,896],{},[631,889,890],{},[329,891,892],{},"The split matches the configured shares.",[631,894,895],{},"The counts are close enough to your shares that chance explains the difference.",[631,897,898],{},"Carry on.",[613,900,901,906,909],{},[631,902,903],{},[329,904,905],{},"The run needs more exposures before the split can be checked against the configured shares.",[631,907,908],{},"Too few contexts have been exposed to tell.",[631,910,911],{},"Wait for more traffic.",[613,913,914,919,922],{},[631,915,916],{},[329,917,918],{},"The split does not match the configured shares.",[631,920,921],{},"The difference is too large to be chance, so results from this run are not reliable. This usually means some contexts evaluate without a stable identifier, or a rule above the split catches part of the traffic.",[631,923,924,925,928,929,933],{},"Use ",[329,926,927],{},"Open the rule tester"," to look for the cause and fix it. Then ",[304,930,932],{"href":931},"#stop-without-a-winner","stop the run"," and start a new one, so the counts start over.",[321,935,937],{"id":936},"compare-the-variations","Compare the variations",[297,939,940],{},"The counts above say how many contexts each variation reached, not which one did better. For that you need the outcome you care about, per variation. You can get it in two ways, and they work together.",[376,942,944],{"id":943},"track-the-outcome-in-configdirector","Track the outcome in ConfigDirector",[297,946,947,948,951],{},"Call ",[316,949,950],{},"track"," when the outcome happens, for the same context you evaluated:",[384,953,954,979],{},[387,955,957],{"className":389,"code":956,"filename":391,"language":392,"meta":393,"style":393},"client.track(\"checkout_completed\", { value: 49 });\n",[316,958,959],{"__ignoreMap":393},[397,960,961,964,966,968,971,974,977],{"class":399,"line":400},[397,962,963],{"class":407},"client.",[397,965,950],{"class":440},[397,967,444],{"class":407},[397,969,970],{"class":414},"\"checkout_completed\"",[397,972,973],{"class":407},", { value: ",[397,975,976],{"class":433},"49",[397,978,471],{"class":407},[387,980,982],{"className":389,"code":981,"filename":508,"language":392,"meta":393,"style":393},"client.track(\"checkout_completed\", { id: \"user-42\" }, { value: 49 });\n",[316,983,984],{"__ignoreMap":393},[397,985,986,988,990,992,994,996,998,1001,1003],{"class":399,"line":400},[397,987,963],{"class":407},[397,989,950],{"class":440},[397,991,444],{"class":407},[397,993,970],{"class":414},[397,995,582],{"class":407},[397,997,468],{"class":414},[397,999,1000],{"class":407}," }, { value: ",[397,1002,976],{"class":433},[397,1004,471],{"class":407},[297,1006,826,1007,1010],{},[329,1008,1009],{},"Tracked events"," card lists each event and, per variation, how many distinct contexts reported it after the split first served them that variation.",[297,1012,1013],{},[355,1014],{"alt":1015,"src":1016},"The Tracked events card, listing trial_started and checkout_completed with the contexts that reported each one under control and treatment-a","\u002Fimg\u002Fscreenshots\u002Fexperiments-tracked-events.webp",[297,1018,1019,1022,1023,1025],{},[304,1020,1009],{"href":1021},"\u002Fmonitoring\u002Factivity#tracked-events"," lists the SDKs that offer ",[316,1024,950],{},", what an event carries and its limits.",[376,1027,1029],{"id":1028},"send-exposures-to-your-analytics-tool","Send exposures to your analytics tool",[297,1031,1032,1033,1036,1037,1040,1041,1045,1046,1050,1051,1055,1056,1059],{},"To analyse the result where your other events already are, report each exposure to that tool from your application. The ",[316,1034,1035],{},"configEvaluated"," hook gives you the variation of each evaluation in ",[316,1038,1039],{},"evaluation.variation",", in the ",[304,1042,1044],{"href":1043},"\u002Fsdks\u002Fbrowser\u002Fjavascript#hooks","browser"," and on the ",[304,1047,1049],{"href":1048},"\u002Fsdks\u002Fserver\u002Fnode-js#hooks","server",". With OpenFeature, the variant is the variation's name, on the ",[304,1052,1054],{"href":1053},"\u002Fsdks\u002Fopenfeature\u002Fweb#evaluation-details-and-hooks","web"," and in ",[304,1057,167],{"href":1058},"\u002Fsdks\u002Fopenfeature\u002Fnode-js#evaluation-details-and-hooks",". The outcomes you compare are the events your application already sends to the tool, and nothing passes through ConfigDirector.",[297,1061,1062],{},"Add the handler before you start the run, so the tool sees every exposure.",[321,1064,1066],{"id":1065},"ship-the-winner","Ship the winner",[297,1068,1069,1070,796,1073,1075],{},"When you have decided, click ",[329,1071,1072],{},"Ship…",[329,1074,339],{}," tab and pick the variation. The dialog shows the targeting rules today and after shipping, and warns you in a live environment. Confirming makes these changes in one save:",[1077,1078,1079,1082,1085],"ul",{},[721,1080,1081],{},"The default targeting rule value becomes the variation you picked.",[721,1083,1084],{},"Every percentage rollout is removed, including one a conditional rule serves, along with any conditional rule left with nothing to serve.",[721,1086,1087],{},"A conditional rule that serves a single value stays, so the contexts it matches keep getting that value.",[297,1089,1090],{},[355,1091],{"alt":1092,"src":1093,"width":1094},"The Ship dialog with treatment-a picked, showing the targeting rules today and after shipping, and a warning that Production is a live environment","\u002Fimg\u002Fscreenshots\u002Fexperiments-ship-dialog.webp",520,[297,1096,1097,1098,1101],{},"The run ends as ",[329,1099,1100],{},"Shipped"," and stays listed on the tab, with its dates, shares and exposures. Your applications get the new value as they do after any targeting rules save.",[297,1103,1104],{},"Shipping applies to one environment, so repeat it in each live environment that runs the experiment.",[376,1106,1108],{"id":1107},"stop-without-a-winner","Stop without a winner",[297,1110,1111,1114,1115,1118],{},[329,1112,1113],{},"Stop run…"," ends the run without choosing a variation. Every percentage rollout is removed, the default targeting rule value stays, and the run is listed as ",[329,1116,1117],{},"Stopped",". A conditional rule that serves a single value stays here too.",[297,1120,1121],{},"There is no pause: a later split is a new run whose counts start from zero. With the same shares, contexts get the same variation they had before.",[297,1123,1124,1125,1127,1128,1130,1131,348,1133,1135],{},"Removing the last percentage rollout by hand on the ",[329,1126,730],{}," tab also ends the run, but lists it as ",[329,1129,778],{},", so use ",[329,1132,1072],{},[329,1134,1113],{}," to keep a record of how the run ended.",[321,1137,1139],{"id":1138},"remove-the-config-once-it-has-settled","Remove the config once it has settled",[297,1141,1142,1143,1146],{},"An experiment is always temporary, so ConfigDirector tracks it for cleanup. Once it has served a single value for 14 days in every live environment with recent activity, it is ",[329,1144,1145],{},"Settled",": its job is done, and the value can live in your code.",[297,1148,1149,1150,1154,1155,1158,1159,1161],{},"A ",[304,1151,1153],{"href":1152},"\u002Fmonitoring\u002Falerts#config-settled","Config settled alert"," then asks you to hardcode the value and remove the config from your code, and the config page shows the value with a copy button. Once your applications stop evaluating the config, it becomes ",[329,1156,1157],{},"Archive Ready"," and you can archive it from the ",[329,1160,364],{}," tab.",[297,1163,1164,1165,1168],{},"A config settles only when its rules can serve nothing else. A conditional rule that stayed after shipping and serves another variation holds it back, and so does a live environment that still runs the split or serves another variation. An experiment can settle on any variation, including ",[316,1166,1167],{},"false"," on a Boolean experiment, and a stopped experiment settles the same way as a shipped one.",[297,1170,1171,1172,1176],{},"Archiving removes the runs and their counts along with the config, so take the numbers first if you want to keep them. ",[304,1173,1175],{"href":1174},"\u002Fmonitoring\u002Flifecycle#settled-temporary-configs","Config Lifecycle"," has the full rules.",[321,1178,1180],{"id":1179},"outside-the-dashboard","Outside the dashboard",[297,1182,1183],{},"You can read a run, ship a variation and stop a run without opening the dashboard:",[1077,1185,1186,1201,1219,1228],{},[721,1187,826,1188,1191,1192,499,1195,348,1198,308],{},[304,1189,257],{"href":1190},"\u002Fintegrations\u002Fcli#experiment-runs",": ",[316,1193,1194],{},"configs runs",[316,1196,1197],{},"configs ship",[316,1199,1200],{},"configs stop",[721,1202,826,1203,1191,1207,499,1210,499,1213,348,1216,308],{},[304,1204,1206],{"href":1205},"\u002Fintegrations\u002Fmcp#what-the-assistant-can-do","MCP server",[316,1208,1209],{},"list_runs",[316,1211,1212],{},"get_run",[316,1214,1215],{},"ship_variation",[316,1217,1218],{},"stop_run",[721,1220,826,1221,1227],{},[304,1222,1223,1226],{"href":253},[316,1224,1225],{},"configdirector-roll-out"," agent skill",", which asks for an explicit yes in a live environment.",[721,1229,826,1230,308],{},[304,1231,267],{"href":1232},"\u002Fintegrations\u002Fadmin-api#experiment-runs-shipping-and-stopping",[297,1234,1235],{},"The CLI, the MCP server and the Admin API do not ask for confirmation in a live environment, so check the environment first.",[321,1237,1239],{"id":1238},"sdk-versions-that-report-exposures","SDK versions that report exposures",[297,1241,1242],{},"These versions and later report which variation served each evaluation:",[607,1244,1245,1258],{},[610,1246,1247],{},[613,1248,1249,1252,1255],{},[616,1250,1251],{},"SDK",[616,1253,1254],{},"Package",[616,1256,1257],{},"Reports exposures since",[626,1259,1260,1275,1288,1301,1314,1328,1341,1355,1369,1383,1397],{},[613,1261,1262,1267,1272],{},[631,1263,1264],{},[304,1265,1266],{"href":106},"JavaScript",[631,1268,1269],{},[316,1270,1271],{},"@configdirector\u002Fclient-sdk",[631,1273,1274],{},"1.11.0",[613,1276,1277,1281,1286],{},[631,1278,1279],{},[304,1280,110],{"href":111},[631,1282,1283],{},[316,1284,1285],{},"@configdirector\u002Freact-web-sdk",[631,1287,1274],{},[613,1289,1290,1294,1299],{},[631,1291,1292],{},[304,1293,115],{"href":116},[631,1295,1296],{},[316,1297,1298],{},"@configdirector\u002Fvue-sdk",[631,1300,1274],{},[613,1302,1303,1307,1312],{},[631,1304,1305],{},[304,1306,126],{"href":127},[631,1308,1309],{},[316,1310,1311],{},"@configdirector\u002Freact-native-sdk",[631,1313,1274],{},[613,1315,1316,1320,1325],{},[631,1317,1318],{},[304,1319,151],{"href":152},[631,1321,1322],{},[316,1323,1324],{},"@configdirector\u002Fnextjs-sdk",[631,1326,1327],{},"1.14.0",[613,1329,1330,1334,1339],{},[631,1331,1332],{},[304,1333,156],{"href":157},[631,1335,1336],{},[316,1337,1338],{},"@configdirector\u002Fnuxt-sdk",[631,1340,1327],{},[613,1342,1343,1347,1352],{},[631,1344,1345],{},[304,1346,167],{"href":168},[631,1348,1349],{},[316,1350,1351],{},"@configdirector\u002Fserver-sdk",[631,1353,1354],{},"1.13.0",[613,1356,1357,1361,1366],{},[631,1358,1359],{},[304,1360,172],{"href":173},[631,1362,1363],{},[316,1364,1365],{},"configdirector-server-sdk",[631,1367,1368],{},"1.9.0",[613,1370,1371,1376,1381],{},[631,1372,1373],{},[304,1374,1375],{"href":201},"OpenFeature Web",[631,1377,1378],{},[316,1379,1380],{},"@configdirector\u002Fopenfeature-web-provider",[631,1382,1274],{},[613,1384,1385,1390,1395],{},[631,1386,1387],{},[304,1388,1389],{"href":217},"OpenFeature Node.js",[631,1391,1392],{},[316,1393,1394],{},"@configdirector\u002Fopenfeature-server-provider",[631,1396,1354],{},[613,1398,1399,1404,1409],{},[631,1400,1401],{},[304,1402,1403],{"href":221},"OpenFeature Python",[631,1405,1406],{},[316,1407,1408],{},"configdirector-openfeature-server-provider",[631,1410,1411],{},"1.8.0",[297,1413,1414,1415,1417],{},"The other SDKs do not report exposures yet, and neither do older versions of these. Contexts using them are still split and served a variation, but the ",[329,1416,691],{}," card does not count them, and it says how many evaluations it left out.",[1419,1420,1421],"style",{},"html pre.shiki code .sLDKn, html code.shiki .sLDKn{--shiki-light:#A0111F;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sbRM4, html code.shiki .sbRM4{--shiki-light:#0E1116;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .suztq, html code.shiki .suztq{--shiki-light:#032563;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sxMNI, html code.shiki .sxMNI{--shiki-light:#023B95;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sEIia, html code.shiki .sEIia{--shiki-light:#622CBC;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":393,"searchDepth":421,"depth":421,"links":1423},[1424,1428,1429,1430,1433,1437,1440,1441,1442],{"id":323,"depth":421,"text":324,"children":1425},[1426,1427],{"id":378,"depth":427,"text":379},{"id":594,"depth":427,"text":595},{"id":701,"depth":421,"text":702},{"id":788,"depth":421,"text":789},{"id":815,"depth":421,"text":816,"children":1431},[1432],{"id":864,"depth":427,"text":865},{"id":936,"depth":421,"text":937,"children":1434},[1435,1436],{"id":943,"depth":427,"text":944},{"id":1028,"depth":427,"text":1029},{"id":1065,"depth":421,"text":1066,"children":1438},[1439],{"id":1107,"depth":427,"text":1108},{"id":1138,"depth":421,"text":1139},{"id":1179,"depth":421,"text":1180},{"id":1238,"depth":421,"text":1239},"Run an A\u002FB test, from creating the experiment to shipping the winner and removing the config","md",null,{"modifiedAt":1447},"2026-11-06T20:10:23.000Z",{"icon":51},{"title":1450,"description":1451},"Running an A\u002FB Test","How to run an A\u002FB test with ConfigDirector. Create an experiment with named variations, split traffic in an environment, read exposures per variation, then ship the winner or stop the run.","c54V3nmSPYKu_G8Wdv0alRTmGONO-6B2o1f13AIr2Rc",[1454,1456],{"title":43,"path":44,"stem":45,"description":1455,"icon":46,"children":-1},"See which value a context would receive from the targeting rules you are editing, and why, before you save",{"title":53,"path":54,"stem":55,"description":1457,"icon":56,"children":-1},"Define a set of users once and use it in the targeting rules of every config in the project",1793996885440]