Skip to content

[DO NOT MERGE] Special release 2.7.24 — 2.7.23 + backported fixes - #451

Closed
ianrumac wants to merge 7 commits into
developfrom
claude/backport-2-7-24-release-2m3hxs
Closed

[DO NOT MERGE] Special release 2.7.24 — 2.7.23 + backported fixes#451
ianrumac wants to merge 7 commits into
developfrom
claude/backport-2-7-24-release-2m3hxs

Conversation

@ianrumac

@ianrumac ianrumac commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

⚠️ Do not merge this PR

This branch is cut from the 2.7.23 tag, not from develop/main. It exists to be tagged and released directly as 2.7.24 via a manual workflow run — it is a review vehicle only. Merging it into develop would downgrade version.env from 2.8.0 to 2.7.24 and conflict with the 2.8.0 changelog (GitHub already flags it as conflicting). Close this PR without merging once 2.7.24 is released.

What this is

A special patch release for users who want the latest fixes but are not ready for the 2.8.0 upgrade (Play Billing 9, custom store products, minSdk 23). It is 2.7.23 + the unreleased fixes cherry-picked from develop:

Plus release prep: version.env → 2.7.24, a stamped ## 2.7.24 changelog section, and a publish input on the Build, Test & Publish workflow so a manual workflow_dispatch on a non-main branch can opt into the full publish/tag/release flow.

How to release

Actions → Build, Test & PublishRun workflow → branch claude/backport-2-7-24-release-2m3hxs → check publish → Run. This publishes to Maven Central, tags 2.7.24, and creates the GitHub release with the changelog section as notes.

Checklist

  • All unit tests pass (SDK compiled and tests covering the backported code run green)
  • Backport verified against develop — remaining diffs are 2.8.0-only features, as intended
  • CHANGELOG.md has a 2.7.24 section (no 2.8.0 section on this branch — it's the 2.7.x lineage)
  • Released via manual workflow run, then this PR closed unmerged

🤖 Generated with Claude Code

https://claude.ai/code/session_01QQGVCTwCQwWYFVHCHosoFg

ianrumac and others added 7 commits July 27, 2026 18:44
…ll events

Superwall-Android never wrote presentation_id into outgoing paywall
event payloads (paywall_page_view, paywall_open, paywall_close, etc.),
which breaks any dashboard funnel that correlates a set of page views
into one paywall session. Confirmed on live ClickHouse data: the field
is 100% empty on Android across every SDK version, vs 0% empty on iOS.

- PaywallCloseReason: add a `description` extension mirroring iOS's
  camelCase close-reason strings (systemLogic, forNextPaywall,
  webViewFailedToLoad, manualClose, none).
- PaywallInfo: add `presentationId`, and serialize it alongside the
  already-modeled-but-never-emitted close_reason/cache_key/build_id in
  eventParams().
- Paywall: add a transient `presentationId` field, threaded through
  getInfo().
- PaywallRequestManager.updatePaywall: mint a fresh UUID presentationId
  on every getPaywall() call that results in a presentation (fresh
  fetch, in-flight-task reuse, and content-cache hit), so repeat
  presentations of a cached paywall get distinct, correlatable IDs.

Trade-off: PaywallLoad.Complete/PaywallProductsLoad.* events track
before updatePaywall runs, so they won't carry presentation_id — same
existing timing gap as experiment_id/variant_id/presentation_source_type.
paywall_open/paywall_page_view/paywall_close all fire after
updatePaywall and reliably get a stable ID.
Translated paywalls rendered in the default language first, then visibly
re-rendered once the template_variables message delivered deviceLocale to
paywall.js (that message is gated on product/billing loading, so it can
take seconds). The web runtime now reads window.__SW_DEVICE_PRELOAD__ at
boot and seeds its locale from it, so inject that global before any page
JavaScript runs:

- Add DevicePreloadScript, a pure builder that serializes the payload
  with kotlinx.serialization so hostile locale strings cannot break out
  of the script, producing exactly:
  window.__SW_DEVICE_PRELOAD__ = {"deviceLocale":"en_US"};
- Install it via WebViewCompat.addDocumentStartJavaScript (androidx.webkit,
  new dependency) when the WebView supports DOCUMENT_START_SCRIPT, and
  fall back to evaluateJavascript in WebViewClient.onPageStarted on older
  WebView versions.
- The locale comes from PaywallViewState.locale, which is the same
  DeviceHelper.locale value later sent as deviceLocale in
  template_variables, so the later message is a visual no-op.
- Unit-test the builder (exact output, quote escaping, longer and
  non-ASCII locales) and add a CHANGELOG entry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01775Up1AYfMgNQybxjnoDSg
The test asserted externalAccountId equals sha256-of-user-123 but never
stubbed storage.read(AppUserId), so userId fell back to the generated
anonymous alias. Stub the stored app user ID like the sibling test does.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UL13jCN87cPLKtmZnTYUrb
The document-start script path required adding androidx.webkit as a new
dependency for every SDK user. It bought little: the paywall runtime
reads window.__SW_DEVICE_PRELOAD__ when its network-fetched bundle
boots, so an evaluateJavascript from onPageStarted lands well before
that — and since the web runtime now seeds exclusively from the preload
global, a missed injection just means today's behavior (wait for
template_variables), never a wrong translation.

This matches how the SDK already injects JS (plain evaluateJavascript,
like the selection/zoom scripts), just hooked at page start rather than
template delivery, which would be too late. DevicePreloadScript and its
tests are unchanged; the script is now built lazily in the hook so it
always uses the freshest locale.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01775Up1AYfMgNQybxjnoDSg
Bump SUPERWALL_VERSION to 2.7.24 and stamp the changelog: this release is
2.7.23 plus the fixes backported from develop (translation first-paint,
Play Store user ID hashing, presentation_id/close_reason/cache_key/build_id
on paywall events), without the 2.8.0 changes (Billing 9, custom store
products, minSdk 23).

Also add a `publish` input to the Build, Test & Publish workflow so a
manual workflow_dispatch on a non-main branch can opt into the full
publish/tag/release flow, which was previously gated to pushes on main.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QQGVCTwCQwWYFVHCHosoFg
@ianrumac ianrumac changed the title Add presentation ID and device locale preload for paywall analytics [DO NOT MERGE] Special release 2.7.24 — 2.7.23 + backported fixes Aug 11, 2026
@ianrumac ianrumac closed this Aug 11, 2026
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.

4 participants