Checklist
Description
registerForInAppForms() loads klaviyo.js into a WebView and waits on a one-shot handshake (the native bridge HandShook message). The current public FormLifecycleEvent only exposes formShown / formDismissed / formCtaClicked, all of which fire after a form is presented. There is no public signal for:
- the forms session becoming ready (handshake completed,
klaviyo.js loaded, listeners active), or
- the session failing/aborting (e.g. the handshake timing out, which currently logs
IAF WebView Aborted: Timeout waiting for Klaviyo.js and destroys the WebView).
formDismissed explicitly does not fire on internal teardowns/aborts, so today there is no way for host apps to observe whether In-App Forms are actually operational.
Motivation / use case
On real devices with a cold WebView cache and a slow network at launch, the handshake exceeds the timeout and the WebView is torn down with no retry and no observable signal. The form never appears for that session, and the app has no way to know it failed. We've had to implement blind, timed re-registration as a workaround precisely because the SDK exposes no success/failure signal to react to. A ready/failed callback would let integrators:
- Confirm forms are functioning (observability / analytics / health checks).
- Implement intelligent retry/backoff on failure instead of guessing.
- Stop retrying once
ready fires, avoiding wasted work.
Proposed Solution
Extend FormLifecycleEvent (or add a separate session-lifecycle callback) with ready/failed cases carrying a reason:
// iOS
public enum FormLifecycleEvent: Equatable, Sendable {
// ...existing formShown / formDismissed / formCtaClicked...
case formsSessionReady
case formsSessionFailed(reason: FormsFailureReason)
}
public enum FormsFailureReason: Equatable, Sendable { case handshakeTimeout, networkError, webViewUnsupported, renderProcessGone, unknown }
Additional Context
- Versions: Android
4.4.0, iOS 5.3.1 (latest at time of filing).
- Today the only evidence of a failed load is an internal log line (
IAF WebView Aborted: Timeout waiting for Klaviyo.js), available only via Logcat/Console with verbose logging — not consumable in code.
- Related: a built-in retry on the handshake would reduce the need for this, but a
failed signal is still valuable for observability even if retry is added.
Checklist
Description
registerForInAppForms()loadsklaviyo.jsinto a WebView and waits on a one-shot handshake (the native bridgeHandShookmessage). The current publicFormLifecycleEventonly exposesformShown/formDismissed/formCtaClicked, all of which fire after a form is presented. There is no public signal for:klaviyo.jsloaded, listeners active), orIAF WebView Aborted: Timeout waiting for Klaviyo.jsand destroys the WebView).formDismissedexplicitly does not fire on internal teardowns/aborts, so today there is no way for host apps to observe whether In-App Forms are actually operational.Motivation / use case
On real devices with a cold WebView cache and a slow network at launch, the handshake exceeds the timeout and the WebView is torn down with no retry and no observable signal. The form never appears for that session, and the app has no way to know it failed. We've had to implement blind, timed re-registration as a workaround precisely because the SDK exposes no success/failure signal to react to. A ready/failed callback would let integrators:
readyfires, avoiding wasted work.Proposed Solution
Extend
FormLifecycleEvent(or add a separate session-lifecycle callback) with ready/failed cases carrying a reason:Additional Context
4.4.0, iOS5.3.1(latest at time of filing).IAF WebView Aborted: Timeout waiting for Klaviyo.js), available only via Logcat/Console with verbose logging — not consumable in code.failedsignal is still valuable for observability even if retry is added.