> For the complete documentation index, see [llms.txt](https://docs.maiagent.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.maiagent.ai/tech/en/api-integration/web-chat-sdk/web-chat-context-data.md).

# Page Context Injection

When Web Chat is embedded in your website, the AI assistant by default has no idea "which page the user is on or what they are looking at." `contextData` lets the embedding site pass arbitrary key-value data in the embed configuration. This data is **automatically sent with every message and injected into the LLM System Prompt**, so the AI assistant can use it directly in conversations and tool calls (Tool / Function Calling).

Common use cases:

* **E-commerce product pages**: Inject `productId` so the assistant doesn't have to ask "Which product are you asking about?" and can directly call the "product lookup" API tool with that product ID
* **Customer support systems**: Inject `ticketId` and `customerId` so the assistant can reference the ticket context directly when handling support workflows
* **Healthcare / form services**: Inject an identifier read from a QR code (such as an issuance serial number) so the assistant automatically includes it when calling the submission API
* **Membership / financial services**: Inject attributes such as membership tier so the assistant provides personalized responses based on identity

{% hint style="info" %}
`contextData` lives under `auth` in the embed configuration, so you must also provide `auth.sourceId` (the user identifier). For details on the auth mechanism, see [Web Chat Embed & SDK](/tech/en/api-integration/web-chat-sdk.md#identify-users).
{% endhint %}

## 1. Quick Start <a href="#quickstart" id="quickstart"></a>

Add `auth.contextData` to `maiagentChatbotConfig` before the embed script:

```html
<script>
  window.maiagentChatbotConfig = {
    webChatId: 'your-web-chat-id',
    baseUrl: 'https://yourdomain.com/web-chats',
    auth: {
      sourceId: 'user-12345',        // Required: unique user identifier
      name: 'John Wang',             // Optional: display name
      contextData: {                 // Arbitrary key-value pairs, injected into the LLM system prompt
        productId: '3021',
        productName: 'Wireless Noise-Canceling Headphones',
      },
    },
  }
</script>
<script src="https://yourdomain.com/js/embed.min.js"></script>
```

After the SDK finishes loading, it automatically runs `auth.setup()`. From then on, **every message** the user sends carries these key-value pairs in its `metadata`, and the backend appends them to the System Prompt in the following format:

```
Contact custom attributes:
- productId: 3021
- productName: Wireless Noise-Canceling Headphones
```

The AI assistant can then reference these values directly in responses and tool calls.

## 2. How It Works <a href="#how-it-works" id="how-it-works"></a>

```mermaid
flowchart LR
  A["Embedding page config:<br/>auth.contextData"] --> B["embed SDK<br/>auth.setup()"]
  B --> C["message.metadata<br/>on every message"]
  C --> D["Backend merges metadata<br/>into System Prompt"]
  D --> E["LLM reads the context"]
  E --> F["Conversation replies /<br/>API tool calls with parameters"]
```

Key characteristics:

* **Sent with each message, not persisted to the database**: `contextData` exists only in frontend memory and is sent with each message's payload. After the user refreshes the page, the embedding page must re-inject it (well suited for short-lived data such as QR codes or sessions)
* **Effective on every conversation turn**: Because it is sent with every message, the AI has continuous access to the latest context throughout the conversation
* **No extra API calls**: It reuses the existing message channel, adding no performance overhead

### Difference from queryMetadata <a href="#context-data-vs-query-metadata" id="context-data-vs-query-metadata"></a>

The two serve completely different purposes—do not mix them up:

|                    | `auth.contextData`                                           | `queryMetadata`                                                   |
| ------------------ | ------------------------------------------------------------ | ----------------------------------------------------------------- |
| Purpose            | Tell the AI about page context (goes into the System Prompt) | Control knowledge base retrieval scope (RAG permission filtering) |
| Visible to the LLM | ✅ Appears in the System Prompt                               | ❌ Not in the prompt, not passed to tools                          |
| Suitable for       | Product IDs, ticket numbers, user identifiers                | Knowledge management permissions, document access scope           |

If you want the AI to "know" a value (for example, to fill it into an API tool parameter), use `contextData`; if you want to restrict "which knowledge documents the AI can retrieve," use [Knowledge Management Permissions (Query Metadata)](/tech/en/authorization-integration/zhi-shi-guan-li-quan-xian-query-metadata-cha-xun-yuan-zi-liao-zong-lan.md).

## 3. Data Rules and Limits <a href="#data-rules" id="data-rules"></a>

The SDK sanitizes the `contextData` you pass in, according to the following rules:

| Rule                   | Behavior                                                                                                                                                |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Value types            | `string` is supported; `number` / `boolean` are automatically converted to strings; other types (object, array, null, etc.) cause the key to be dropped |
| Maximum number of keys | Up to **50** key-value pairs; anything beyond that is dropped                                                                                           |
| Reserved keys          | Keys that conflict with existing system metadata are dropped (see the list below)                                                                       |
| Empty object `{}`      | After sanitization it is empty, treated as not provided; metadata contains no custom keys                                                               |
| Sanitization behavior  | Silent—no errors are raised, and message sending is not blocked                                                                                         |

**Reserved key list** (dropped if passed in, to avoid overwriting system fields):

`contact_name`, `timezone`, `latitude`, `longitude`, `accuracy`, `locale`, `language`, `working_directory`

{% hint style="warning" %}
**Security is the embedding site's responsibility**: `contextData` is injected by the embedding page, and MaiAgent does not verify its origin with signatures or encryption. Do not inject confidential data that end users should not learn (values go into the LLM prompt and the AI may repeat them in responses). If the data is personally identifiable (such as a national ID number), the embedding site must ensure the source is trustworthy (for example, a signed QR code / session) and comply with personal data protection regulations.
{% endhint %}

## 4. Updating and Clearing <a href="#update-and-clear" id="update-and-clear"></a>

The lifecycle of `contextData` follows `auth.setup()`:

* **Update**: Calling `MaiAgent.auth.setup()` again **fully overwrites** the current `contextData` (it does not merge)
* **Clear**: Calling `auth.setup()` without `contextData` clears previously injected values; `MaiAgent.auth.signOut()` also clears it, preventing carryover across identities

```jsx
// When switching pages in an SPA, update the context to the new product
MaiAgent.auth.setup({
  sourceId: 'user-12345',
  contextData: {
    productId: '4552',
    productName: 'Portable Bluetooth Speaker',
  },
})

// When leaving the product page, clear the context (omitting contextData clears it)
MaiAgent.auth.setup({
  sourceId: 'user-12345',
})
```

## 5. Examples <a href="#examples" id="examples"></a>

### 1. E-commerce product page: AI answers based on the current product <a href="#example-product-page" id="example-product-page"></a>

Scenario: The AI assistant is configured with a "product lookup" API tool (queries product details by product ID). Web Chat is embedded on the product detail page. When the user asks "Is this right for me?", the assistant should answer about the current product directly instead of asking back.

```html
<!-- Product detail page, e.g. product_detail.php?id=3021 -->
<script>
  // Get the current product info from the page (however your site implements it)
  const productId = new URLSearchParams(location.search).get('id')

  window.maiagentChatbotConfig = {
    webChatId: 'your-web-chat-id',
    baseUrl: 'https://yourdomain.com/web-chats',
    auth: {
      sourceId: 'visitor-' + productId,   // Based on your member / visitor identification logic
      contextData: {
        productId,                         // The AI fills in this ID when calling the "product lookup" tool
        productName: document.querySelector('.product-title')?.textContent ?? '',
      },
    },
  }
</script>
<script src="https://yourdomain.com/js/embed.min.js"></script>
```

When the user asks "How long does the battery last on this one?", the System Prompt already contains `productId: 3021`, so the AI directly calls the "product lookup" tool with `id=3021` to fetch the product details and answer—no need to ask "Which product are you asking about?".

{% hint style="info" %}
**Recommended: guide the model with system prompt instructions**: Whether the context is actually used by tools is decided by the LLM based on the prompt. Explicit guidance in the AI assistant's [system prompt](/tech/en/ai-agents/system-prompt.md) greatly improves reliability, for example: "When Contact custom attributes contains a productId, it means the user is currently viewing that product. Prioritize calling the product lookup tool with this ID to answer, and do not ask the user which product they mean."
{% endhint %}

### 2. Customer support system: bring in ticket context <a href="#example-support-ticket" id="example-support-ticket"></a>

```jsx
window.maiagentChatbotConfig = {
  webChatId: 'your-web-chat-id',
  baseUrl: 'https://yourdomain.com/web-chats',
  auth: {
    sourceId: currentUser.id,
    name: currentUser.displayName,
    contextData: {
      ticketId: 'T-2026-0142',
      customerId: currentUser.id,
      plan: 'enterprise',
    },
  },
}
```

When the user opens the conversation, the AI already knows the ticket number and the customer's plan tier, so it can handle the ticket's follow-up workflow directly without the customer repeating the details.

### 3. Identifier injection: QR code / URL parameters <a href="#example-identifier-injection" id="example-identifier-injection"></a>

Scenario: The service page is opened via a QR code or a parameterized link, and the AI needs to automatically include the identifier when calling the submission API.

```jsx
const params = new URLSearchParams(location.search)

window.maiagentChatbotConfig = {
  webChatId: 'your-web-chat-id',
  baseUrl: 'https://yourdomain.com/web-chats',
  auth: {
    sourceId: params.get('sessionId'),
    contextData: {
      formId: params.get('formId'),       // Form / document identifier
      userRef: params.get('userRef'),     // User reference number
    },
  },
}
```

After the AI guides the user through the flow, it automatically fills `formId` and `userRef` into the request body when calling the submission tool (such as `SubmitAnswers`).

## 6. Verification and Troubleshooting <a href="#troubleshooting" id="troubleshooting"></a>

**How do I confirm contextData is taking effect?**

1. Open the Network tab in the browser developer tools and watch the WebSocket messages: the `metadata` in the outgoing message payload should contain the keys you injected
2. Ask the AI assistant directly: "Do you know what my productId is?"—if injection succeeded, the AI can answer directly
3. In the admin console's conversation monitoring, inspect the actual prompt used for that message; it should contain the `Contact custom attributes` section

**Common issues**

| Issue                                         | Cause and resolution                                                                                                                       |
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| contextData has no effect at all              | Confirm that `auth.sourceId` is provided (required; without it, `auth.setup()` does not run)                                               |
| Some keys are missing                         | Check whether they use reserved keys, whether the value is an unsupported type (object / array), or whether the 50-pair limit was exceeded |
| Context disappears after refresh              | Expected behavior: it is not persisted to the database, so the page must re-inject it on each load                                         |
| The AI does not use the context in tool calls | Add explicit guidance in the system prompt (see the hint in Example 1 above)                                                               |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.maiagent.ai/tech/en/api-integration/web-chat-sdk/web-chat-context-data.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
