> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.ada.cx/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.ada.cx/_mcp/server.

# Reporting differences from the Chat SDK

The Messaging SDK and the [Chat SDK](/chat/introduction/overview) report to the same Ada dashboard. Some values change when an AI Agent moves from the Chat SDK to the Messaging SDK. Each change on this page is intentional. For each change, this page gives what you see in reporting, why the value differs, and what you need to do.

The changes affect [Reports](/docs/optimization/performance/reports/performance-reports), the [Conversations view](/docs/optimization/conversations/response-training), the [Data Export API](/docs/optimization/conversations/data-export), [webhooks](/reference/webhooks/overview), and the events that the SDK sends to your own code.

## Summary

| Difference                                                                                            | Where you see it                                                              | Action needed                                                                                   |
| ----------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| [Opened conversations on preload installs](#opened-conversations-on-preload-installs)                 | Reports, Conversations view                                                   | Compare periods with the Engaged count                                                          |
| [Surveys scored but not submitted](#surveys-scored-but-not-submitted)                                 | CSAT reports, Conversations view, Data Export API                             | Compare historical periods using the release period and survey configuration                    |
| [File links in handoff integration transcripts](#file-links-in-handoff-integration-transcripts)       | Conversations view, end user chat history                                     | None                                                                                            |
| [Meta field limits](#meta-field-limits)                                                               | Variable filters, Conversations view, Data Export API                         | Keep meta fields within the limits                                                              |
| [Campaign events for proactive messages](#campaign-events-for-proactive-messages)                     | Your own event counters                                                       | Update your event handlers                                                                      |
| [Session checks during an API incident](#session-checks-during-an-api-incident)                       | Reports, Conversations view, Data Export API (earlier Chat SDK releases only) | None                                                                                            |
| [Reconnection rows after a page refresh](#reconnection-rows-after-a-page-refresh)                     | Conversations view                                                            | None                                                                                            |
| [Zendesk Chat in private mode when the tab closes](#zendesk-chat-in-private-mode-when-the-tab-closes) | Conversation end time, webhooks                                               | Expect a delayed webhook                                                                        |
| [Retry after a failed message](#retry-after-a-failed-message)                                         | Conversations view, message counts                                            | None                                                                                            |
| [Greeting failures during an API incident](#greeting-failures-during-an-api-incident)                 | Reports, Conversations view                                                   | None                                                                                            |
| [Carousel link clicks in widgets](#carousel-link-clicks-in-widgets)                                   | Link Click Performance report, Data Export API                                | None for the Ada carousel. A widget you built must classify its links as `link` or `web_window` |

## Opened conversations on preload installs

The Chat SDK setting `preload: true` does not exist in the Messaging SDK. The Messaging SDK ignores the setting.

* **What you see:** The **Opened** count in the [Conversations breakdown](/docs/optimization/performance/reports/performance-reports#conversations-breakdown) report drops on the day of the move. The conversation total in the Conversations view drops on the same day. The **Engaged** count does not change. The period-over-period change for **Opened** shows the drop.
* **Why it differs:** With `preload: true`, the Chat SDK loads the chat window and sends the greeting when the page loads. Each visit by an end user without an active conversation creates a conversation that contains only the greeting. The Messaging SDK sends the greeting when the end user opens the chat window. A conversation exists only after the end user opens the chat. Installs that use `parentElement` or `headless` mode are not affected. Both SDKs start the conversation at load time in those modes.
* **What to do:** No configuration change is needed. Use the **Engaged** count to compare periods across the move. If a report or an alert uses **Opened** as a traffic measure, record the date of the move.

## Surveys scored but not submitted

Messaging now matches Chat survey counting in the widget:

* Every first answer inside the conversation or post-agent survey counts, including comments and feedback choices. Scores send immediately. Other first answers send after 1000 ms without another change. Required follow-up questions do not delay this count.
* In the **End Chat** survey, score, resolution, Customer Effort Score, and Net Promoter Score selections count before **Submit** only when no enabled question is required.
* In **End Chat** and follow-up forms, comments and feedback choices wait for **Submit**. Only configured required questions block **Submit**. A response can count without a satisfaction score.

On a direct survey page, selections count before **Submit** only when no enabled question is required.

Reports count each conversation once, including when an end user selects a score and then selects
**Submit**. Messaging conversations before this release followed the old partial-response rule.
Those periods can have fewer completed responses for the same end user behavior. Keep the release
period and survey configuration in mind when comparing CSAT results.

## File links in handoff integration transcripts

This applies to a file that an end user uploads during a [handoff integration](/docs/handoffs/handoff-management/handoff-integrations) conversation.

* **What you see:** In the Conversations view, the upload appears as a picture or as a link on the Messaging SDK. On the Chat SDK, the same upload appears as a file name only. In the end user's chat history, a Chat SDK link stops working 7 days after the upload. A Messaging SDK link continues to work.
* **Why it differs:** The Messaging SDK stores the storage key of the file with the message. Ada uses the key to create a new link each time the transcript loads. The Chat SDK does not store the key. Its link expires 7 days after the upload.
* **What to do:** No change is needed.

## Meta field limits

The Messaging SDK applies limits to [metaFields](/messaging/web/sdk-api-reference#metafields) and [sensitiveMetaFields](/messaging/web/sdk-api-reference#sensitivemetafields). The Chat SDK sends every value without a client-side limit. Ada stores an object value from the Chat SDK as text and accepts a string up to 100,000 characters.

* **What you see:** A string value longer than 100,000 characters is cut to 100,000 characters. A value that is an object or an array is dropped. A key longer than 256 characters is dropped. A dropped field is absent from the **Variable** filter in Reports and in the Conversations view. It is also absent from the **Meta variables** panel, from search, and from the Data Export API.
* **Why it differs:** The string-value limit matches API storage. The SDK also limits keys and value types.
* **What to do:** Keep each field within the limits. Convert an object to a string of 100,000 characters or fewer before you pass it. The SDK writes a notice to the browser console when it drops or cuts a value.

## Campaign events for proactive messages

This applies to code that subscribes to the `ada:campaigns:*` events with [subscribeEvent](/messaging/web/sdk-api-reference#subscribeevent). Ada reporting does not use these events.

* **What you see:** Your own counters that use these events show different totals. The Messaging SDK sends `ada:campaigns:shown`, `ada:campaigns:opened`, `ada:campaigns:engaged`, and `ada:campaigns:dismissed` for a proactive message that a URL rule or `triggerProactive` starts. The Chat SDK sends no campaign events for those messages.
* **Why it differs:** The Messaging SDK reports what the end user sees. One `campaignKey` identifies the bubble from display to dismissal. When the chat window is open, or in `headless` or `parentElement` mode, no bubble renders and no event is sent.
* **What to do:** If your code counts impressions, filter on the `campaignKey` values that you expect. A `campaignKey` can now be the key of a proactive message. If your code counts dismissals, add a handler for `ada:campaigns:dismissed`.

## Session checks during an API incident

* **What you see:** During an incident on the Ada API, the end user continues the same conversation on both SDKs. Earlier Chat SDK releases created extra conversations. On those releases, the **Opened** count and the Conversations view showed a new conversation for each affected end user, the earlier conversation closed by timeout, and the Data Export API showed a new `chatter_id` for that end user.
* **Why it differs:** When the page loads, both SDKs check that the saved session is still valid. Both SDKs keep the saved session when the check gives no result, such as a network error or a server error. Both create a new session only when the Ada API reports the session as expired or invalid. Earlier Chat SDK releases treated a check with no result as an invalid session and created a new `chatter_id`.
* **What to do:** No change is needed. If you compare a period before the Chat SDK change, expect the extra **Opened** conversations described above.

## Reconnection rows after a page refresh

This applies to a [Zendesk Chat](/docs/handoffs/zendesk/zendesk-chat/zendesk-chat-configuration) handoff.

* **What you see:** The Chat SDK adds a reconnection row to the Conversations view transcript each time the end user refreshes the page during the handoff. The Messaging SDK does not add this row. Reports do not count these rows.
* **Why it differs:** After a refresh, both SDKs reconnect to the same Zendesk chat. The Chat SDK reports each reconnection to Ada, which creates a presence row. The Messaging SDK reports the first connection and a reconnection after a dropped connection. It does not report a reconnection that a page refresh causes.
* **What to do:** No change is needed.

## Zendesk Chat in private mode when the tab closes

This applies to installs that set [privateMode](/messaging/web/sdk-api-reference#privatemode), or set Customer Persistence to Forget After Reload, and use a Zendesk Chat handoff.

* **What you see:** If the end user closes the tab during the handoff, the conversation ends later on the Messaging SDK. On the Chat SDK, the agent conversation ends when the tab closes. The conversation returns to the AI Agent and closes by timeout after 1 day without activity. On the Messaging SDK, the conversation stays in the handoff state and closes by timeout up to 3 days later. The conversation end time, the [`v1.conversation.ended`](/reference/webhooks/overview) webhook, and the [automated resolution](/docs/optimization/conversations/resolution-rate-optimization) classification arrive later. The conversation ends by timeout on both SDKs.
* **Why it differs:** The Messaging SDK does not end the agent conversation when the tab closes. With `privateMode`, the browser keeps nothing, so the end user cannot return to the agent conversation. With Forget After Reload, the browser keeps the handoff session until the tab closes. A page refresh returns the end user to the same agent conversation. A closed tab does not.
* **What to do:** No configuration change is needed. If your systems act on the `v1.conversation.ended` webhook, expect the delay for these conversations.

## Retry after a failed message

* **What you see:** When a message from an end user fails to send, the Chat SDK shows a **Retry** control. Each retry can add a duplicate of the message to the transcript and to the message counts. The Messaging SDK shows a failure notice. It shows **Retry** only when the Ada API rejected the message. A Messaging SDK transcript contains no duplicate from a retry.
* **Why it differs:** A retry sends the message again with the same message identifier. The Ada API does not detect a repeated identifier. A retry after a network error, a timeout, or a server error can therefore store the message twice. The Messaging SDK does not offer **Retry** in those cases. It also does not offer **Retry** when the Ada API reports a processing failure for a stored message. It shows a failure notice instead.
* **What to do:** No change is needed. If an end user reports that a message did not send, ask them to send the message again.

## Greeting failures during an API incident

* **What you see:** During an incident on the Ada API, the Chat SDK creates conversations that contain only a greeting. The Messaging SDK does not. On the Messaging SDK, a conversation exists only when the end user sends a message. That conversation has no greeting in its transcript. The **Opened** count is lower on the Messaging SDK during the incident.
* **Why it differs:** When the greeting request fails with a server error or a timeout, the Chat SDK shows a full-page error. It then reloads the page on a schedule. Each reload sends the greeting again until one succeeds. The Messaging SDK marks the greeting as sent before the request and does not send it again. A repeated greeting request can create two greetings. The Messaging SDK sends the greeting again only when the Ada API rejects the request with a client error.
* **What to do:** No change is needed.

## Carousel link clicks in widgets

This applies to a widget message whose carousel reports link clicks to Ada.

* **What you see:** The Link Click Performance report and the `link_was_clicked` column of the Data Export API count fewer carousel clicks on the Messaging SDK. Three cases lose the click. The widget classifies the click as `article`. The link uses a scheme that a link in a message cannot use, such as `javascript:`. The URL is longer than 2048 characters. A click that the widget classifies as `link` or `web_window`, with a link that a message can use, counts on both SDKs.
* **Why it differs:** The Chat SDK forwards every carousel click to Ada as the widget reports it. For an `article` click, Ada also writes a transcript entry for an article that the click does not name. An unchecked link is stored on the message and appears in reporting. The Messaging SDK reports only the clicks that Ada can record completely.
* **What to do:** No change is needed for the Ada carousel. If you built a widget that reports carousel clicks, classify its links as `link` or `web_window`. Report links that a message can use, such as `http` or `https` URLs.