VoidhashDocs
DevelopersHelp centerGuidesAPI reference
Dashboard
Get started
Introduction
Quickstart
How Voidhash works
Glossary
Versions and releases
Concepts
Teams, projects and environments
API keys
Products and perks
Offers
Subscription lifecycle
People and identity
Events
Features
Paywalls in your app
Feature flags and A/B tests
Paywall components
Push notifications
Ad attribution in your app
Client SDKs
React Native
Swift
Kotlin
Web
Your backend
Node.js
PHP
Go
Rust
Other languages
Payment sources
Forward store notifications
Developer tools
CLI
MCP server
Query analytics with VoidQL
Web SDK
Web quickstart
Script tag
Identify users
Evaluate feature flags
Track
Track events
Page views and attribution
Privacy
Privacy and consent
Browser storage
Connect a consent tool
Keep data out of analytics
Revenue and attribution
Sell on the web
Stripe revenue
Web-to-app handoff
Delivery
First-party proxy
Tracking domain
Reference
Web SDK reference
Errors
Troubleshooting

Web-to-app handoff

Keep one person from the ad click on your website to the purchase and use in your app.

In a web-to-app funnel, a visitor arrives from an ad, signs up and often pays on your website, then installs your app. Voidhash keeps them one person across both: the campaign, the Stripe purchase and their app activity belong together, and access bought on the web works in the app. The handoff is your user ID, passed to identify() on both sides.

Install the SDK on both sides

Install the web SDK on your landing and signup pages, and a mobile SDK in your app: React Native, Swift or Kotlin. Use the same Voidhash project for both.

Identify on the web when the account is created

Call identify() as soon as the visitor has an account, before checkout. The anonymous visitor and their campaign become your user.

Website
await voidhash.identify("user_123", { email: "ada@example.com" });

Pay with the user's ID

Create the Stripe Checkout Session with the same user ID. See Stripe revenue.

Server
await stripe.checkout.sessions.create({
  metadata: { voidhash_distinct_id: "user_123" },
  subscription_data: { metadata: { voidhash_distinct_id: "user_123" } },
  // ...
});

Identify in the app after sign-in

When the user signs in to the app, identify them with the same ID. The app's anonymous install is merged into the user, and perks granted by the Stripe purchase are available in the app.

App (React Native)
await voidhash.client.identify("user_123");

The order does not matter: if a user signs up in the app first, the website's anonymous visitor is merged into that user when identify() runs.

Make the app sign-in effortless

Any sign-in that ends with identify() and the same user ID completes the handoff. To keep drop-off low:

  • Ask for the email address early in the web funnel and use it as the app login.
  • After the web purchase, show a download page with a one-time login link or code from your backend.
  • Identify in the app right after sign-in, before checking access, so purchased perks are there on the first screen.

Credit Android installs to the campaign

A Google Play link can carry the visitor's latest campaign, so the Android SDK credits the install to it. Build the link with playStoreUrl() when the visitor follows it:

downloadButton.addEventListener("click", () => {
  window.location.href = voidhash.playStoreUrl("com.example.app");
});

The link's referrer holds the latest touch's utm_* parameters, click IDs, campaign_id, adset_id and ad_id, plus the click time as touch_at. The Android SDK reads them after install with the same rules as the web, and the click time keeps an old click from looking new. Without analytics consent, without a touch, or before initialize() resolves, it returns the plain link.

What a store link does not do

  • It carries no identity. No anonymous or user ID is ever put in a link, as a shared link must not hand someone's purchases to another person. The install stays a separate person until the user signs in.
  • The App Store has no referrer. On iOS, sign-in is the only handoff.

Next steps

  • Identify users
  • Stripe revenue
  • People and identity

Something wrong or missing on this page? Tell us by email or on Discord.

PreviousStripe revenueNextFirst-party proxy

On this page

Install the SDK on both sidesIdentify on the web when the account is createdPay with the user's IDIdentify in the app after sign-inMake the app sign-in effortlessCredit Android installs to the campaignWhat a store link does not doNext steps