Intempt Docs

Server-Side Experiments Overview

Deliver personalized experiences and run A/B tests from your backend using Intempt's Choose API — no flicker, SEO-safe, framework-agnostic.

Server-Side Experiments

Overview & Mental Model

Server-side Experiences allow you to deliver personalized experiences and run A/B tests directly from your backend, instead of applying variations in the browser.

Unlike client-side experiences — where variations are applied after the page loads — server-side Experiences are resolved before the response is sent to the client. Intempt decides what a user should see; your backend decides how to render it.


Client-Side vs Server-Side

Client-SideServer-Side
When decidedIn the browser after JS executesBefore rendering, on the server
FlickerCan cause flicker/layout shiftNone — user gets correct version on first paint
SEOLimited control over crawlersFully SEO-safe
Works withBrowser onlySSR, APIs, mobile backends

How It Works

  1. Configure Experiences or personalizations in Intempt
  2. Your backend calls the Choose API before rendering
  3. Intempt returns the decision (variation assignment)
  4. Your backend applies the result before responding

Intempt does not modify your UI automatically. It only returns a decision. Rendering is always your responsibility.


What Intempt Decides vs What You Control

Intempt handlesYour backend controls
User eligibilityHTML rendering
Experience assignmentAPI response structure
Variation consistencyFeature flags
Segmentation & targeting logicLayout selection
Personalization rulesUI composition

This separation keeps Intempt framework-agnostic.


When to Use Server-Side Experiences

  • Server-rendered pages (SSR)
  • Feature flags controlled from the backend
  • Personalized API responses
  • SEO-sensitive landing pages
  • Mobile app backends
  • High-performance personalization

Choose API

The Choose API resolves server-side Experiences and personalizations before rendering.

Endpoint

POST https://api.intempt.com/v1/{orgName}/projects/{projectName}/optimization/choose-api?apiKey=YOUR_API_KEY
ParameterDescription
orgNameIntempt organization name
projectNameProject containing the Experience
apiKeyAPI key (query parameter)

Resolve by Experience Name

{
  "identification": {
    "userId": "user_123456"
  },
  "names": ["demo-server-side-experience"],
  "device": "mobile",
  "sessionId": "my_session_XXX"
}

Resolve by Group

{
  "identification": {
    "userId": "user_123456"
  },
  "groups": ["my-group"]
}

Identity Methods

Use userId if the user already exists in Intempt:

{
  "identification": {
    "userId": "user_123456"
  }
}

Optional context fields:

FieldDescription
sessionIdSession identifier for consistency within a session
device"mobile" or "desktop"

Example Response

{
  "choices": [
    {
      "name": "demo-server-side-personalization-most-popular",
      "group": "my-group",
      "body": {
        "label": "My most popular products PERSONALIZATION",
        "products": [
          {
            "price": "250.0",
            "title": "PMC Bronze 9mm",
            "category": "Ammunition"
          }
        ]
      }
    }
  ]
}

Applying Experience Results

Response Structure

{
  "choices": [
    {
      "name": "experience-name",
      "group": "group-name",
      "body": {}
    }
  ]
}

Application Patterns

Text / Content replacement

{ "headline": "Try our new premium plan" }

Replace server-rendered copy before sending the response.

Feature flags

{
  "enableNewCheckout": true,
  "layout": "v2"
}

Apply logic before rendering — never after.

Structured personalization

{
  "products": [{ "title": "Product A", "price": "250.0" }]
}

Insert into HTML, API response, or mobile payload.

Handling Multiple Choices

  • Iterate over choices
  • Match by name
  • Never rely on index order

Fallback Handling

If the API fails or returns no choices, always render the default experience. Define defaults for every Experience before deploying.


End-to-End Flow

  1. User request — SSR, API, or mobile backend receives request
  2. Identify user — resolve userId or sourceId + profileId
  3. Call Choose API — before any rendering occurs
  4. Intempt resolves — eligibility, targeting, variation allocation
  5. Backend applies result — layout, data, flags
  6. Respond to client — HTML, JSON, or mobile payload
  7. Consistency — same identity always returns the same Experience
  8. Measure & iterate — track events normally

Use Cases

Use CaseWhy Server-Side
SEO-sensitive pagesNo flicker, crawler-safe, deterministic HTML
Feature flagsTreat as config, always define defaults
Personalized contentStructured payloads, predictable schema
Multi-tenant / B2BUse accountId, separate account vs user logic
Mobile & APIPlatform-agnostic payloads, backend-controlled rollouts

Common Mistakes

  • Calling Choose API after rendering has started
  • Expecting Intempt to inject UI automatically
  • Encoding business logic inside Experience bodies
  • Not defining fallback defaults

When NOT to Use Server-Side Experiences

  • Micro-interactions and DOM-only changes
  • Ultra-high-frequency UI events
  • Cases where client-side rendering is acceptable

Summary

Intempt decides what should happen. Your backend decides how it happens.

  • Faster delivery — decision made before the response
  • No flicker — correct version on first paint
  • SEO-safe — crawler always sees final HTML
  • Full backend control — framework-agnostic integration

On this page