Skip to content
InfluToDocs

Install the SDK

Add InfluTo to a Capacitor, Ionic, Cordova or web app

Use @influto/web in Capacitor, Ionic, Cordova, PWAs and browsers — capture referral links, accept typed codes, and connect RevenueCat or store purchases.

@influto/web adds creator attribution to any app whose code runs in a WebView or a browser: Capacitor (including Ionic React, Angular and Vue), Apache Cordova, installed PWAs, Trusted Web Activities and plain web apps. It follows the same contract as the native SDKs, and adds web-only ways to pick up a referral exactly: the launch URL, deep links, and the Google Play Install Referrer. Plan for an afternoon; most of it goes into the purchase side.

Package @influto/web, with subpaths /capacitor, /cordova, /pwa, /revenuecat and /react
Latest version 1.0.1
Registry npm
Runtimes Capacitor / Ionic, Cordova, PWAs and TWAs, browsers — any ES2019 browser or WebView
Builds ESM, CommonJS, and a script-tag build
Dependencies None. React 17+ only if you use @influto/web/react

Install

Terminal
npm install @influto/web
# Capacitor / Ionic apps (device info, storage, deep links):
npm install @capacitor/device @capacitor/preferences @capacitor/app

The Capacitor plugins are optional but recommended: @capacitor/device for device details, @capacitor/preferences for storage that survives WebView resets, @capacitor/app for deep links. Run npx cap sync after adding them. Missing plugins fall back to browser defaults.

No bundler? Load https://cdn.jsdelivr.net/npm/@influto/web@1/dist/index.global.js with a <script> tag and use window.InfluTo.

Initialize

TypeScript
import InfluTo from '@influto/web';
import { capacitorAdapters } from '@influto/web/capacitor'; // Capacitor / Ionic only

// Call once at startup (Capacitor: after platform ready; PWA: on page load)
await InfluTo.initialize({
  apiKey: 'YOUR_API_KEY',
  appVersion: '1.2.3',
  ...(await capacitorAdapters()),   // omit in a plain PWA / browser
  // RevenueCat apps: revenueCat: revenueCatCapacitor(Purchases)  (from '@influto/web/revenuecat')
});

Call initialize once, at the app root, and wait for it before calling anything else:

Runtime When
Capacitor / Ionic At app start, after the platform is ready — not inside an Ionic page, which can be cached and re-entered
Cordova After deviceready: await whenDeviceReady() from @influto/web/cordova first
PWA / browser On page load

initialize throws when it fails — a wrong key, no network — with an InfluToApiError (status, body) for API errors. Catch it, log it, and carry on: the next launch tries again. If it hasn't succeeded, checkAttribution and reportPurchase throw "not initialized". It resolves to the app's init result (also available later from getInitResult()). A typical Capacitor startup, in order:

influto.ts
import InfluTo from '@influto/web';
import { capacitorAdapters, listenForCapacitorLaunchUrls } from '@influto/web/capacitor';
import { revenueCatCapacitor } from '@influto/web/revenuecat';
import { Purchases } from '@revenuecat/purchases-capacitor';

export async function startInfluTo() {
  await Purchases.configure({ apiKey: 'appl_…' }); // RevenueCat apps: configure it first
  try {
    await InfluTo.initialize({
      apiKey: import.meta.env.VITE_INFLUTO_API_KEY,
      appVersion: '1.4.0',
      ...(await capacitorAdapters()),
      revenueCat: revenueCatCapacitor(Purchases),
    });
  } catch (error) {
    console.warn('InfluTo initialize failed', error); // retried on the next launch
    return;
  }
  await listenForCapacitorLaunchUrls(InfluTo); // deep links → referral claim
  const attribution = await InfluTo.checkAttribution();
  const { appUserID } = await Purchases.getAppUserID();
  await InfluTo.identifyUser(appUserID);
}

The API key starts with it_ and is on Setup & SDK; one key works for development and production. Keep it out of committed source — for example in a gitignored .env.local read through your bundler.

Option Default What it does
apiKey required The app's SDK key (it_…)
debug false Logs [InfluTo] lines to the console
appVersion "unknown" Your app version, sent with the startup call
runtime detected capacitor, cordova, twa, pwa or browser
storage, device, http localStorage, browser detection, fetch Adapters; capacitorAdapters() and cordovaAdapters() fill storage / device / runtime for you
revenueCat none RevenueCat binding — see Purchases
captureLaunchCode true Read influto_code / influto_click from the page URL at startup
cleanUrl true Remove the influto_* parameters from the address bar afterwards
purchaseSource none Store-direct apps: where purchases come from — see Purchases
autoCapture true Report purchases from purchaseSource automatically
oneTimeProductIds none Your Android one-time and consumable product IDs

Detect referred users

TypeScript
const attribution = await InfluTo.checkAttribution();
if (attribution.attributed) {
  // User came from a referral — show a special offer / extended trial.
  // With a RevenueCat binding the SDK also sets influto_code + influto_referral.
  console.log('Referred by', attribution.referralCode);
}

// Web deep links: referral links send web visitors to your app URL with
// ?influto_code=…&influto_click=… — the SDK claims them automatically.
Field Meaning
attributed true when the install came from a creator's link or code
referralCode The creator's code, uppercase
attributionMethod link_param (the link carried the code into the app), ip_device_match (link-click matching) or manual_entry (a code the user applied)
clickedAt, clickId When the link was clicked, and which click was claimed
message A short explanation, for logs

Attribution is decided once per install and stored; later calls return the stored answer. Only a failed request is retried. checkAttribution is fail-soft: on a network or server error it returns attributed: false and stores nothing. In React, useInfluToAttribution(enabled) from @influto/web/react returns { loading, attribution, error, refresh }; pass enabled = false until initialize has resolved.

The web SDK can claim a referral exactly, from the code the link carries, in three ways. A code picked up later re-opens an earlier "organic" answer on the next checkAttribution call; an attributed install keeps its creator. Without a carried code, InfluTo falls back to link-click matching within 72 hours — see attribution.

The launch URL (PWAs and web apps)

Set Settings → General → Web app URL. Referral links send desktop visitors — and phone visitors when your app has no store listing for their platform — to that URL with ?influto_code=…&influto_click=… appended. initialize reads both from the query or a hash-router fragment, stores them, and cleans the address bar.

listenForCapacitorLaunchUrls(InfluTo) passes the cold-start URL and every appUrlOpen event to the SDK; it returns a function that removes the listener. In Cordova, or with your own handler, call InfluTo.handleLaunchUrl(url). Call either after initialize and before checkAttribution.

The Play Install Referrer (Android)

Google Play links from InfluTo carry the code and click in Play's referrer parameter. On first launch, read the referrer string with an Install Referrer plugin (@capgo/capacitor-install-referrer or cordova-play-install-referrer) and hand it over after initialize, before checkAttribution:

TypeScript
await InfluTo.captureInstallReferrer(referrer); // the raw referrer string from the plugin
const attribution = await InfluTo.checkAttribution();

Identify the user

Call identifyUser(appUserId, properties?) as soon as you know who the user is, with the same ID your purchases are keyed on — for RevenueCat, the app user ID (see the startup example). InfluTo uses it to credit a RevenueCat purchase when the influto_code attribute didn't make it; checkAccess, setReferralCode and reportPurchase use it by default. Call it once per sign-in, ideally in the user's first session — not on every render.

Track events

TypeScript
await InfluTo.trackEvent({ eventType: 'paywall_viewed', appUserId: userId, properties: { placement: 'onboarding' } });

Events show on Real-Time Events and never create conversions or commission. Every call gets an event ID, so an accidental double call counts once. For trial_started, subscription_purchased and subscription_renewed the ID is derived from the event, user and properties, so the same event counts once even across launches; include something that changes per occurrence in properties when the event can repeat, or pass eventId yourself.

Let users type a code

TypeScript
// Validate, then apply a code the user typed
const result = await InfluTo.applyCode('FITGURU30');
if (result.valid && result.applied) {
  // Unlock the offer
}

// React / Ionic React: drop in the ready-made field
import { ReferralCodeInput } from '@influto/web/react';
<ReferralCodeInput onCodeApplied={(code) => {/* ... */}} />

// Free-access codes: (await InfluTo.setReferralCode(code)).grantsAccess → unlock
// premium, and gate premium on (await InfluTo.checkAccess()).hasAccess.

applyCode(code, appUserId?) validates the code and applies it if it's valid. Codes are trimmed and uppercased for you. An invalid code comes back with valid: false and an error_code: INVALID_FORMAT, CODE_NOT_FOUND, CODE_EXPIRED or NETWORK_ERROR. If you build your own field, write your own copy: message and influencer can contain the creator's personal name.

ReferralCodeInput from @influto/web/react is a plain, unstyled form: an input and a button. It pre-fills a link-attributed code and applies the code on submit.

Prop Default Notes
onCodeApplied(code, result) — The code was valid and applied
onInvalid(result) — The code was rejected
appUserId identified user The user to bind the code to
prefill true Pre-fill from a link-attributed install
showCampaignName / showReferrerName false / false Show a creator's name only with their consent
placeholder, buttonLabel 'Referral or access code', 'Apply' Texts, for translation
className, style, inputClassName, buttonClassName — Styling

Angular, Vue or no framework: build the field yourself on applyCode. More on the UX: Let users enter a referral code. All props: UI components.

Purchases

InfluTo only pays commission on purchases it has verified with the store. Choose exactly one path per platform — see Choose a validation path.

RevenueCat

Pass a binding as revenueCat. When checkAttribution finds a referral, or a code is applied, the SDK sets influto_code (the code) and influto_referral (the string "true") through it. Then connect the webhook — see RevenueCat.

Your RevenueCat SDK Binding (from @influto/web/revenuecat)
@revenuecat/purchases-capacitor 7.5.10+ revenueCatCapacitor(Purchases)
@revenuecat/purchases-js 1.4.0+ (Web Billing) revenueCatJs(() => Purchases.getSharedInstance())
cordova-plugin-purchases revenueCatCordova(window.Purchases)
Anything else A function (attrs) => …, or any object with setAttributes(map) — wrap it in revenueCatBinding(obj) to get retries

The bindings retry a failed write up to 3 times (options retries, backoffMs, onError). To attach one after initialize, call InfluTo.attachRevenueCat(binding) — before checkAttribution.

Store-direct

Pass a purchase source as purchaseSource. When the app is set to store-direct in Settings → Validation and autoCapture isn't false, initialize starts reporting new purchases and back-fills existing ones, each once.

Runtime Purchase plugin Source
Capacitor @capgo/native-purchases capgoNativePurchasesSource(NativePurchases, { oneTimeProductIds }) from /capacitor
Cordova cordova-plugin-purchase v13 cordovaPurchaseSource(CdvPurchase.store, { oneTimeProductIds }) from /cordova
TWA on Google Play Digital Goods API (Chrome 101+) digitalGoodsSource({ oneTimeProductIds }) from /pwa

The Digital Goods API has no purchase event, so call InfluTo.syncExistingPurchases() after each checkout. requestPlayBillingPurchase(itemId) from /pwa runs a Play Billing checkout and returns { purchaseToken }, or null if the user cancelled. You can also drive capture yourself with enableAutoPurchaseCapture(source, { backSync, oneTimeProductIds }) and disableAutoPurchaseCapture().

  • iOS needs the StoreKit 2 signed transaction. capgoNativePurchasesSource passes it on; with cordova-plugin-purchase, check that your setup exposes one, or iOS reports fail.
  • Android one-time products: the Capacitor and Cordova sources don't carry a price, and a one-time purchase without a price is recorded at $0. Report those yourself with price and currency. digitalGoodsSource looks the price up.

To report purchases yourself instead, set autoCapture: false and call reportPurchase:

TypeScript
// Store-direct only (no RevenueCat). Attach a purchase source and purchases are
// captured automatically — TWA/PWA on Play: digitalGoodsSource(); Capacitor:
// capgoNativePurchasesSource(); Cordova: cordovaPurchaseSource(). Or report manually:
await InfluTo.reportPurchase({
  platform: 'android',             // or 'ios'
  purchaseToken: token,            // Android: Play Billing purchaseToken
  // signedTransaction: jws,       // iOS: StoreKit 2 JWS
});
  • In a browser or PWA, always pass platform ('ios' or 'android'); the SDK refuses to guess when it detects web.
  • It throws an InfluToApiError. 503: the exchange rate was briefly unavailable — retry later. 400: the platform isn't set to store-direct yet. 409: an Android one-time purchase isn't in the PURCHASED state yet.
  • Android one-time products need productId, plus price and currency.

Set-up, credentials and testing: Store-direct.

Free-access codes

Free-access codes give a user premium without a purchase. Redeem one with setReferralCode(code, appUserId?); it uses the identified user when you don't pass one, and a code with no user is refused. The result tells you what happened: grantsAccess, freeAccess, entitlement and expiresAt. applyCode doesn't return these flags; after it, result.campaign?.campaign_type === 'FREE_ACCESS' tells you the code was a free-access code.

Gate premium on your store entitlement or InfluTo's answer: entitlementActive || (await InfluTo.checkAccess()).hasAccess. checkAccess caches a positive answer for 5 minutes, never caches a negative one, and returns hasAccess: false on errors. See Free access codes.

Verify

After the first successful initialize, Setup & SDK shows "Integrated — SDK connected" with the platform, @influto/web and the SDK version it last saw. With debug: true the SDK logs each step, and Real-Time Events lists your events and purchases. For the full end-to-end test and the integration status checklist, see Verify the integration. To test attribution again, clearAttribution() forgets the stored attribution, code and launch code.

Platform notes

Capacitor and Ionic

  • With @capacitor/preferences installed, capacitorAdapters() stores the SDK's state there. WebView localStorage is wiped when androidScheme or iosScheme changes; pass { usePreferences: false } to keep localStorage anyway.
  • The reported platform is the native OS (ios or android).
  • In a web dev build (ionic serve) the RevenueCat Capacitor plugin is a stand-in, so attribute writes do nothing there. Test on a device.

Cordova

  • A fresh Cordova template blocks the API twice: add <access origin="https://influ.to" /> to config.xml and connect-src https://influ.to to the Content-Security-Policy meta tag.
  • Start with await whenDeviceReady() and pass ...cordovaAdapters() to initialize; storage stays in localStorage.
  • RevenueCat has deprecated its Cordova plugin. For a new app, prefer Capacitor.

PWAs, TWAs and web apps

  • Set the Web app URL so referral links can hand the code to your app.
  • The platform comes from the user agent the same way InfluTo classifies a click: phones are ios or android, everything else web.
  • A TWA on Google Play can sell through Play Billing (digitalGoodsSource()); web checkout through RevenueCat Web Billing works with revenueCatJs(). iOS home-screen web apps can't sell in-app purchases, but attribution still works.
  • isStandalone() and hasDigitalGoods() from /pwa tell you whether you're running installed and whether Play Billing is available.

Script tag

The script-tag build contains the core SDK only; the subpath helpers need a bundler. Pass revenueCat as a plain function that calls your RevenueCat SDK's setAttributes.