Enabling adaptive content

Choose an authentication method to pass user data to GitBook.

To start customizing your documentation experience for your readers, you'll need to enable adaptive content and decide how your visitor data is passed to GitBook. This lets your site's content dynamically adapt based on who's viewing it.

Enable adaptive content

Before you’re able to pass user data to GitBook, you’ll need to configure your site to use adaptive content.

Head to your site’s settings, and enable “Adaptive content” from your site’s audience settings. Once enabled, you’ll get a generated “Visitor token signing key”, which you’ll need in order to continue the adaptive content setup.

Enable adaptive content

Set your adaptive schema

After enabling adaptive content, you’ll need to define a schema for the types of claims you expect GitBook to receive when a user visits your site.

The adaptive content schema should reflect how these claims are structured when sent to GitBook.

For example, if you expect a visitor to potentially be a beta user in your product, you would set an adaptive schema similar to:

{
  "type": "object",
  "properties": {
    "isBetaUser": {
      "type": "boolean",
      "description": "Whether the visitor is a Beta user.”
    },
  },
  "additionalProperties": false
}

This will also help you use autocomplete when configuring your claims in the condition editor.

If you intend to work with unsigned claims, you will need to declare the claims you are expecting in the schema under an “unsigned” prop alongside your signed claims.

{
  "type": "object",
  "properties": {
    "isBetaUser": {
      "type": "boolean",
      "description": "Whether the visitor is a Beta user.”
    },
    // Add unsigned claims
    "unsigned": {
      "type": "object",
      "description": "Unsigned claims of the site visitor.",
      "properties": {
        "language": {
          "type": "string",
          "description": "The language of the visitor",
          "enum": [
            "en",
            "fr",
            "it"
          ]
        }
      },
      "additionalProperties": false
    }
  }
  "additionalProperties": false
}

Next, you’ll need to decide how you want to pass your visitor data to GitBook.

Ways to pass visitors's data to GitBook

GitBook provides different ways to pass visitor data to adapt your site's content. Choose the option that best suits your needs:

  • Cookie method: When you don't require full authentication for your docs but still want to use your user’s data to adapt your public site's content based on their information.

  • Visitor authentication method: When you need your site to be behind authentication and want to customize the site's content based on your authenticated user’s information.

Methods

Method
Use-cases
Ease of setup
Security
Format
Transport

Signed cookie gitbook-visitor-token

API test credentials, customer identification, etc

Require signing and a custom domain

Properties can only be defined by the backend

JWT

Cookies

Public cookie gitbook-visitor

Feature flags

Easy to use

Visitor can override the properties

JSON

Cookies

Signed query parameter token

Require signing and a custom domain

Properties can only be defined by the backend

JWT

URL

Query parameters gitbook_<prop>=

Easy to use

Visitor can override the properties

JSON

URL

This approach only works if your site is served under a subdomain of your application domain. To set up a custom domain on your site follow the steps outlined in this section.

When you don’t need your documentation to be fully behind authentication but still want to tailor its content for users logged into your application, you can store their user attributes as a JSON Web Token in a cookie named gitbook-visitor-token tied to your product domain.

To set this up, you'll need to adjust your application’s login flow to include the following steps:

1

Generate a JWT when users logs in to your application

Whenever a user logs in to your product, generate a JWT that contains selected attributes of your authenticated user's info.

2

Sign the JWT using the site's visitor signing key

Then, make sure to sign the JWT using the site's visitor signing key, which you can find in your site’s audience settings after enabling Adaptive Content.

3

Finally you need to store the signed JWT containing your user's info into a wildcard session cookie under your product domain.

For example, if your application is served behind the app.acme.org domain, the cookie will need to be created under the .acme.org wildcard domain.

Here's what the code of your application login handler might look like after incorporating these steps:

import * as jose from 'jose';

import { Request, Response } from 'express';

import { getUserInfo } from '../services/user-info-service';
import { getFeatureFlags } from '../services/feature-flags-service';

const GITBOOK_VISITOR_SIGNING_KEY = process.env.GITBOOK_VISITOR_SIGNING_KEY;
const GITBOOK_VISITOR_COOKIE_NAME = 'gitbook-visitor-token';


export async function handleAppLoginRequest(req: Request, res: Response) {
   // Your business logic for handling the login request
   // For example, checking credentials and authenticating the user
   //
   // e,g:
   // const loggedInUser = await authenticateUser(req.body.username, req.body.password);

   // After authenticating the user, retrieve user information that you wish
   // to pass to GitBook from your database or user service.
   const userInfo = await getUserInfo(loggedInUser.id);
      
   // Build the JWT payload with the user's information
   const gitbookVisitorClaims = {
       firstName: userInfo.firstName,
       lastName: userInfo.lastName,
       isBetaUser: userInfo.isBetaUser
       products: userInfo.products.map((product) => product.name),
       featureFlags: await getFeatureFlags({userId: loggedInUser.id})
   }
   
   // Generate a signed JWT using the claims
   const gitbookVisitorJWT = await new jose.SignJWT(gitbookVisitorClaims)
     .setProtectedHeader({ alg: 'HS256' })
     .setIssuedAt()
     .setExpirationTime('2h') // abritary 2 hours expiration
     .sign(GITBOOK_VISITOR_SIGNING_KEY);
     
  // Include a `gitbook-visitor-token` cookie including the encoded JWT in your
  // login handler response
  res.cookie(GITBOOK_VISITOR_COOKIE_NAME, gitbookVisitorJWT, {
     httpOnly: true,
     secure: process.env.NODE_ENV === 'production',
     maxAge: 2 * 60 * 60 * 1000, // abritary 2 hours expiration
     domain: '.acme.org' //
  });
  
  // Rest of your login handler logic including redirecting the user to your app
  res.redirect('/'); // Example redirect
}

After successfully signing the cookie for a user when they log into your app, they will have associated data with them upon visiting your published GitBook site.

Following the example above, the data available for this user could look like:

{
   "visitor":{
      "claims":{
         "firstName": "John",
         "lastName": "Doe",
         "isBetaUser": true,
         "products":[
            "PRODUCT_A",
            "PRODUCT_C"
         ],
         "featureFlags":{
            "PRODUCT_V2_FEATURE": true
         }
      }
   }
}

Pass unsigned claims via query parameters

After setting up your schema to accept unsigned claims, you’ll be able to pass them through the URL of your published site.

For instance, in the example above, we can pass the language claim to our published site when visiting this url:

https://docs.acme.org/?visitor.language=fr

Visitor authentication method

GitBook offers out-of-the box solutions to protect your docs. Integrations for Auth0, Okta, Azure AD, and AWS Cognito allow you install an integration to enforce a log-in screen before being able to access your published site.

Depending on which visitor authentication method you’re using, you’ll still need to configure a few more things depending on which integration you’re using in order to send the right data to GitBook.

Head to the relevant guide for full instructions on setting up adaptive content with visitor authentication.

Last updated

Was this helpful?