Skip to content

Conversation

@sumeruchat
Copy link
Collaborator

@sumeruchat sumeruchat commented Oct 14, 2025

🐛 Problem

Wolt reported that their self-hosted custom fonts aren't rendering in Iterable in-app messages on Android. The same fonts work perfectly on iOS and Web, but Android users see fallback fonts instead of Wolt's branded typography.

🔍 Root Cause

The issue was in IterableWebView.loadDataWithBaseURL() - it was passing an empty string as the baseURL parameter. This caused the WebView to use about:blank as the origin instead of a proper web origin.

When the HTML tried to load Wolt's custom fonts from https://webfonts.wolt.com/, the browser's CORS policy blocked the requests because:

  • Wolt's server CORS is configured to allow https://app.eu.iterable.com
  • But the WebView was requesting from about:blank origin
  • CORS mismatch = blocked fonts = sad customers 😢

✅ Solution

Added a configurable WebView base URL parameter that customers can set to match their CORS configuration:

  • New config option: setWebViewBaseUrl() in IterableConfig.Builder
  • Backward compatible: Defaults to empty string (original behavior) if not set
  • Flexible: Works for any customer domain, not just Iterable's
  • Internal implementation: Added IterableUtil.getWebViewBaseUrl() helper method

🚀 Usage

For Wolt (fixes the CORS issue):

IterableConfig config = new IterableConfig.Builder()
    .setWebViewBaseUrl("https://app.eu.iterable.com")  // Matches their CORS config
    .build();
IterableApi.initialize(context, apiKey, config);

For existing customers (no change needed):

IterableApi.initialize(context, apiKey);  // Still works exactly the same

@sumeruchat sumeruchat changed the title Fix WebView CORS issue with self-hosted custom fonts SDK-113 Fix WebView CORS issue with self-hosted custom fonts Oct 14, 2025
return this.endpoint;
}

String getWebAppBaseUrl() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: Lack of consistency, the method above has the visibility public and this doesn't. Is it intentional?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch will also make it public for consistency

Copy link
Member

@Ayyanchira Ayyanchira left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking great Sumeru!

Copy link
Contributor

@davidtruong davidtruong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The functionality looks fine to fix the font fetching, however we should make it more extensible and future proof.

public enum IterableDataRegion {
US("https://api.iterable.com/api/"),
EU("https://api.eu.iterable.com/api/");
US("https://api.iterable.com/api/", "https://app.iterable.com"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't make sense that they are hardcoding app.iterable.com as the webappbaseurl since iterable isn't serving the request. It local html that is getting rendered into the application.

We should change this to be configurable and set by the client so that they can use whatever they want. If we have it as iterable.com, if we were to change this in the future, it would break any clients tied to the domain.

try {
IterableConfig config = getInstance().config;
if (config != null && config.dataRegion != null) {
return config.dataRegion.getWebAppBaseUrl();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have we tried testing with with other domains? Is it simply the existence of the url domain or a certain domain that they are expecting for CORS.

Copy link
Contributor

@davidtruong davidtruong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@sumeruchat sumeruchat merged commit 2443374 into master Oct 21, 2025
7 of 8 checks passed
@sumeruchat sumeruchat deleted the feature/SDK-113-fix-baseurl-cors-issues branch October 21, 2025 17:58
sumeruchat added a commit that referenced this pull request Oct 23, 2025
* InApp-Display-E2E:
  Deleting md files for integration
  Cleaning up further
  Added retry if button not found for reliabililty
  Using server campaign send in InApp Activity
  URL handler functionality tested
  Retry For sync now removed
  Two config initialization problem
  SDK-113 Fix WebView CORS issue with self-hosted custom fonts (#952)
  MOB-11639 Background Initialization (#946)
  [MOB-12181] - Prepare for 3.6.1
  Committing just whats needed. Removing code
  [MOB-11844] - Support edge to edge to InApps
  updating the queries selection
  uncommenting the queries
  updating runs on to allow the workflow to progress
  Adding initial CodeQL workflow
  Adding initial CodeQL workflow
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants