Issue Symptoms

iOS and Android behave differently when it comes to Pre-chat and VisitorInfo objects and this can make unifying your application behaviors confusing.

The VisitorInfo object allows you to set the information about the visitor before starting the chat. In contrast, the PreChatForm object collects that information once the chat starts.

Initially, the idea was to use one or the other in your workflow, but not both at once, which has now been updated on iOS. 

The workflow with JWT authentication also modifies the behavior of Chat. For more information, refer to the documentation (Android|iOS) or see this article: Enabling authenticated users with the Chat SDK.

Resolution Steps

Disclaimer: This article is provided for instructional purposes only. Zendesk does not support or guarantee the code. Post any issues you have in the comments section or try searching for a solution online.

iOS

The logic in iOS is as follows:

  1. Take the ChatAPIConfiguration's visitorInfo and department properties.
  2. Take the ChatConfiguration's preChatFormConfiguration data requirements.
  3. If the underlying properties of VisitorInfo are nil or empty strings, and their corresponding data requirements are not .hidden, then show the field.
  4. If the underlying properties of department are nil or empty strings, and their corresponding data requirements are not .hidden, then show the field.
  5. The SDK shows the form to the user. The user fills in the details or skips any .optional fields at their discretion.
  6. The SDK gathers the information entered in the form.
    If any field was skipped, it falls back to the configuration details that were there. If that’s empty, no details are sent.
  7. The SDK assigns the department and calls chat.profileProvider.setVisitorInfo(visitorInfo) with the VisitorInfo details of the form (merging the entered data with the API configuration where not filled).

Example:

func status(for info: String?) -> FormFieldStatus {
info?.isEmpty == true ? .optional: .hidden
}

let chatAPIConfig = ChatAPIConfiguration()
chatAPIConfig.visitorInfo = visitorInfo
chatAPIConfig.department = departmentName
chat.configuration = chatAPIConfig
chat.profileProvider.setVisitorInfo(visitorInfo)
let chatUIConfig = ChatConfiguration()
chatUIConfig.preChatFormConfiguration = .init(name: status(for: visitorInfo.name),
email: status(for: visitorInfo.email),
phoneNumber: status(for: visitorInfo.phoneNumber),
department: status(for: form.departmentId))
// pass chatUIConfig into buildUI(engines:, configs:)

Android

For versions prior to SDK Chat 3.2.0:

In Android, the logic is different. The VisitorInfo gets erased entirely if the PreChatForm is enabled, regardless of if the field is Required, Optional or Hidden.

One way to work around this limitation is to update the VisitorInfo once the Chat is started (except the department which is not editable once the chat is started):

  1. Create a VisitorInfo object.
  2. Fill it with already known information about the user.
  3. Configure the pre-chat form to ask for the missing information.
  4. Set up the observer.
  5. Start the Chat activity.

Once the PreChat is completed and the chat goes to STARTED status, the visitor information is updated.

Example:

boolean visitorSet = false; // Generic condition to ensure that you only set those info once

// ...

public void
setupObserver(){
final ObservationScope observationScope = new ObservationScope();
Chat.INSTANCE.providers().chatProvider().observeChatState(observationScope, new Observer<ChatState>() {
@Override
public void update(ChatState chatState) {
ChatSessionStatus chatStatus = chatState.getChatSessionStatus();
// Status achieved after the PreChatForm is completed
if (chatStatus == ChatSessionStatus.STARTED) {
// Update the information MID chat here. All info but Department can be updated
if (!visitorSet) {
// Add here the code to set the visitor info - visitorInfo would be a VisitorInfo type variable containing all the information to set
profileProvider.setVisitorInfo(visitorInfo, null);
visitorSet = true;
}

} else {
// There are few other statuses that you can observe but they are unused in this example
Log.d("DEBUG", "[observerSetup] - ChatSessionUpdate -> (unused) status : " + chatStatus.toString());
}
}
});
}

Update the provided code scripts to suit your workflow.

From Version 3.2.0 onward:

The latest SDK allows a more flexible use of the PreChatForm with VisitorInfo. See this article for more information: Setting information for the chat session.

This can work natively by following the example in the documentation.

Powered by Zendesk