Skip to content

In-App Forms: allow configuring the forms load/handshake timeout (and add retry) #599

Description

@kodypeterson

Checklist

Description

The In-App Forms WebView handshake is bounded by the global request timeout (Registry.config.networkTimeout, default 10s on Android; equivalent on iOS) and performs no retry. If klaviyo.js doesn't load and handshake within that window, the WebView is aborted and In-App Forms are dead for the rest of the session. InAppFormsConfig currently only exposes sessionTimeoutDuration — there's no way to tune the load timeout independently.

Motivation / use case

The 10s handshake is a single attempt sharing the global network timeout, which is too tight for cold-cache first loads on slow/real-world networks. Concretely: on a fresh install over a slow connection, klaviyo.js can't download + handshake in 10s, the session aborts, and the form never appears — until a later launch warms the WebView cache. Working around this by raising the global networkTimeout is undesirable because it also affects analytics/event request behavior.

We'd like a forms-specific load timeout (and, ideally, built-in retry/backoff) so we can give the first cold load enough room without touching unrelated network behavior.

Proposed Solution

Add load-timeout (and optional retry) options to InAppFormsConfig:

// Android
InAppFormsConfig(
    sessionTimeoutDuration = 1.hours,
    loadTimeout = 30.seconds,   // handshake/load timeout, independent of networkTimeout
    maxLoadRetries = 2          // optional built-in retry/backoff on load failure
)

Additional Context

  • Versions: Android 4.4.0, iOS 5.3.1.
  • Android reference: the handshake timer is scheduled with Registry.config.networkTimeout in KlaviyoWebViewClient and, on expiry, logs IAF WebView Aborted: Timeout waiting for Klaviyo.js and destroys the WebView with no retry.
  • Even a built-in retry alone (without a configurable timeout) would resolve the common cold-cache case; both together would be ideal.
  • Pairs naturally with the failed lifecycle event in the related issue — together they let integrators either rely on built-in retry or implement their own against a real failure signal.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions