Skip to content

Appbrew SDK ​

Add Linkrunner attribution to an Appbrew Shopify app with the @linkrunner/appbrew tracker

Appbrew builds Shopify mobile apps from config. @linkrunner/appbrew plugs Linkrunner into that system as an analytics tracker, so installs, events, revenue, identity, deep links and uninstalls are attributed without per-event code.

The package is an adapter over the React Native SDK. rn-linkrunner does the work; @linkrunner/appbrew translates Appbrew's events and lifecycle into SDK calls.

PackageRole
@linkrunner/appbrewAppbrew tracker. LinkrunnerTrackerV2 extends AnalyticsTrackerV2.
rn-linkrunnerLinkrunner React Native SDK. Native module.

Requirements ​

  • An Appbrew app built on the @gauntlet/* packages
  • @linkrunner/appbrew 0.2.0 or higher and rn-linkrunner 3.1.0 or higher
  • iOS 15.0 or higher, Android minSdk 24
  • A Linkrunner project token from Project Settings

1. Install ​

bash
pnpm add @linkrunner/appbrew rn-linkrunner
cd ios && pod install

The package declares requiresNativeBuild: true. Adding or updating it needs a new binary build and a store release.

2. Register the tracker ​

In src/app/App.tsx, alongside Appbrew's own trackers:

typescript
import { AnalyticsProvider } from '@gauntlet/analytics'
import { LinkrunnerTrackerV2 } from '@linkrunner/appbrew'

AnalyticsProvider.getInstance().addTracker(new LinkrunnerTrackerV2())

Do not put the token in code. It arrives at runtime from the Appbrew dashboard.

Sample apps register trackers inside if (!__DEV__). Move this line outside that guard to test in a debug build, or pass { token, debug: true } to the constructor for local runs only.

3. Configure in the Appbrew dashboard ​

The Appbrew team enters the settings per store. They reach the app as config.integrations.linkrunner, and the tracker reads them on every launch. Only token is required.

SettingDefaultPurpose
tokenrequiredLinkrunner project token. Without it the tracker stays disabled.
secretKey, keyIdunsetSDK signing.
debugfalseVerbose SDK logs.
disableIdfafalseSkip IDFA on iOS even when ATT is granted.
enablePIIHashingfalseHash email and phone on device before sending.
trackScreenViewsfalseForward screen_view and page_view. Off because they are the highest-volume events.
deeplinkRoutingtrueRoute the resolved deferred deep link into Appbrew's router.
uninstallTrackingtrueRegister the push token for uninstall tracking.
enableRefundsfalseForward refund as removePayment. Verify order id mapping for your store first.
consentIsEEA, consentAdUserData, consentAdPersonalizationunsetGoogle Ads consent, each granted, denied or unknown. Sent before init. See Consent.
enableTCFConsentCollectionfalseLet the SDK read TCF consent from the device CMP on Android.
clevertapIntegrationtrueSend the CleverTap ID to Linkrunner when clevertap-react-native is installed.
analyticsIdentifierstrueAttach Firebase Analytics ids to signup and setUserData.
eventsMapper, paramsMapper, eventsWhitelist, paramsWhitelistunsetRename or restrict events and params (JSON).

4. Native setup ​

Exclude the SDK's preferences from auto-backup in AndroidManifest.xml, or a reinstall reads as an existing install:

xml
<application
  android:dataExtractionRules="@xml/linkrunner_backup_rules"
  android:fullBackupContent="@xml/linkrunner_backup_descriptor">

Both resource files ship inside rn-linkrunner. Permissions and the Play Install Referrer dependency are merged automatically.

Deep links need your Linkrunner domain in the iOS Associated Domains entitlement and an Android intent filter with autoVerify. Follow Deep Linking Setup.

What the tracker does on its own ​

AppbrewLinkrunner
App openinit, then setCustomerUserId with the device id so guests are attributed
purchasecapturePayment with transaction_id as the payment id
refundremovePayment, only when enableRefunds is on
signup, login, customer detailssignup once per install and customer, setUserData after
logoutIdentity reset to the device id
Every other eventtrackEvent with the Appbrew name unchanged and Meta catalog fields added from items[]
Link opened with the app installedhandleDeeplink. Appbrew routes it
First open after installgetAttributionData, and the deferred link is routed once per install
Push tokensetPushToken for uninstall tracking
CleverTap installedsetAdditionalData with the CleverTap ID
Firebase Analytics installedga_app_instance_id and ga_session_id on user data

Map your events to standard commerce events in Dashboard → Meta Ads → Event Mapping (add_to_cart → AddToCart, view_item → ViewContent, payment type DEFAULT → Purchase). Without the mapping, events are stored but never sync to Meta.

Using the attribution API ​

Everything above is automatic. Use these calls when your app needs the campaign context itself. Each is exported from @linkrunner/appbrew and waits for the tracker to initialise.

Getting attribution data ​

Read the campaign that drove the install and the deferred deep link. Use it for referral codes or campaign-specific onboarding.

typescript
import { getAttributionData } from '@linkrunner/appbrew'

const attribution = await getAttributionData()
// { deeplink?: string, campaignData?: { id, name, type, adNetwork, ... } }

Returns undefined when no token is configured or the install has no attribution. One native call per launch, shared with deferred routing.

Google Ads attribution needs consent before init. Without a consent management platform, set the three consent settings in the Appbrew dashboard. With one, call setConsent from its callback and again whenever the choice changes:

typescript
import { setConsent } from '@linkrunner/appbrew'

setConsent({
  isEEA: 'granted',
  hasConsentForDataUsage: 'granted',
  hasConsentForAdsPersonalization: 'denied',
})

Leave a signal out rather than sending unknown as a denial. See Google Integrated Conversion Measurement.

The tracker reports every link that arrives through React Native's Linking. Push taps do not: Appbrew's push module navigates from the notification payload directly. Report those so a push campaign shows as a re-engagement:

typescript
import { handleDeeplink } from '@linkrunner/appbrew'

messaging().onNotificationOpenedApp(async (message) => {
  const link = message.data?.link
  if (typeof link === 'string' && link.startsWith('http')) {
    await handleDeeplink(link)
  }
})

Extra user fields ​

id defaults to the current customer, or the device id for guests:

typescript
import { setAdditionalData, setUserData } from '@linkrunner/appbrew'

await setUserData({ mixpanel_distinct_id: distinctId })
await setAdditionalData({ clevertapId })

The same five calls exist as methods on the LinkrunnerTrackerV2 instance.

Function Placement Guide ​

Register LinkrunnerTrackerV2 once. The tracker handles the required React Native SDK calls below through Appbrew's lifecycle; do not duplicate them in your app. Call the exported handleDeeplink helper only for links that bypass the tracker, such as push notification taps.

FunctionRequirementWhere to PlaceWhen to Call
linkrunner.initRequiredAppbrew tracker lifecycle (automatic)When the app opens with a configured token
linkrunner.signupRequiredAppbrew identity lifecycle (automatic)Once per install and customer
linkrunner.setCustomerUserIdRequiredAppbrew identity lifecycle (automatic)At app open and when the customer identity changes
handleDeeplinkRequiredAutomatic for incoming links; push notification handlers for links that bypass the trackerWhen the app opens through a deep link
getAttributionDataOptionalCampaign-specific onboarding or referral flowWhen your app needs install attribution
setUserDataOptionalUser data or analytics integration flowWhen you add fields to the current user
setAdditionalDataOptionalThird-party integration setupWhen the CleverTap ID is available
setConsentOptionalConsent settings or your CMP callbackBefore initialization and when consent changes
linkrunner.trackEventOptionalAppbrew event lifecycle (automatic)When Appbrew emits an event
linkrunner.capturePaymentOptionalAppbrew purchase lifecycle (automatic)When Appbrew emits purchase
linkrunner.removePaymentOptionalAppbrew refund lifecycle (automatic)When Appbrew emits refund and enableRefunds is on
linkrunner.setPushTokenOptionalAppbrew push token lifecycle (automatic)When a push token is available and uninstall tracking is on

Testing ​

  1. Build with debug: true and look for Linkrunner initialised successfully in the console.
  2. Open Events Settings. The install and events appear as you use the app.
  3. Place an order and confirm one payment appears. Relaunch and confirm it is not duplicated.
  4. Install through a campaign link on a fresh device and confirm getAttributionData() returns the deeplink.

See Integration Testing for the full checklist.

Troubleshooting ​

SymptomCause
no token in config.integrations.linkrunner in the consoleThe token is not set for this store in the Appbrew dashboard
No events at allThe tracker is registered inside if (!__DEV__), or the whitelist excludes them
Events in Linkrunner but not in MetaEvent mapping missing under Meta Ads → Event Mapping
Reinstalls counted as existing installsAndroid backup rules missing from AndroidManifest.xml
Deep link opens the app but does not navigateDomain verification incomplete. See Deep Linking Setup
Duplicate paymentscapturePayment also called from a Shopify webhook with a different payment id
getAttributionData() returns undefinedNo token, or the app was installed directly from the store

Need help? Contact support@linkrunner.io