# A/B testing

Serve one of two responses from a function on Azion's global network, choosing the group at random and recording it in a cookie. Use this pattern to run randomized experiments, such as comparing two page variants, without sending traffic to an origin to decide which version to show.

```js
  function handleRequest(request) {
    const NAME = "TestA/B"
    const TEST_RESPONSE = new Response("Cookie A")
    const CONTROL_RESPONSE = new Response("Cookie B")
  
    const cookie = request.headers.get("cookie")
    if (cookie && cookie.includes(`${NAME}=a`)) {
      return CONTROL_RESPONSE
    }
    else if (cookie && cookie.includes(`${NAME}=b`)) {
      return TEST_RESPONSE
    }
    else {
      const group = Math.random() < 0.5 ? "test" : "control"
      const response = group === "control" ? CONTROL_RESPONSE : TEST_RESPONSE
      response.headers.append("Set-Cookie", `${NAME}=${group}; path=/`)
  
      return response
    }
  }
  
  addEventListener("fetch", event => {
    event.respondWith(handleRequest(event.request))
  })
```

## How it works

The `fetch` handler reads the incoming `Cookie` header with `request.headers.get("cookie")`. When the header contains `TestA/B=a` the function returns the control response, and when it contains `TestA/B=b` it returns the test response. When neither is present, `Math.random()` picks the test or control group at roughly 50/50, and `response.headers.append("Set-Cookie", ...)` writes the chosen group into the `TestA/B` cookie so the browser sends it on the next request. `event.respondWith()` then returns that `Response` to the client.

## Related resources

- [JavaScript examples](/en/documentation/platform/functions/javascript-examples.md): Browse the other ready-to-use examples you can copy into a function.
- [FetchEvent](/en/documentation/devtools/runtime/api-reference/fetch-event.md): Reference for the `fetch` event and the request the handler receives.
- [Response](/en/documentation/devtools/runtime/api-reference/response.md): Reference for the response object this example builds and sets a cookie on.
- [Functions limits](/en/documentation/platform/functions/limits.md): The ceilings a single invocation of this function runs inside, and the ones that vary by plan.
- [Quickstart](/en/documentation/platform/functions/quickstart.md): What an account needs before a function can run, and the steps that put one in the path of a request.
- [Query usage data from Functions](/en/documentation/guides/platform/observability/query-functions-usage-data-with-graphql.md): Read back the compute time and the invocations this function has consumed.
