Overview
When you use tools like Amplitude, Adjust, AppsFlyer, or other platforms alongside Superwall, integration attributes help you:- Unify analytics across platforms
- Track attribution data
- Build cross-platform cohorts
- Analyze user journeys
- Connect subscription events to marketing campaigns
Setting Integration Attributes
Use thesetIntegrationAttributes function from useUser to link user IDs:
import { useUser } from "expo-superwall";
function App() {
const { setIntegrationAttributes } = useUser();
useEffect(() => {
// Set integration attributes
setIntegrationAttributes({
adjustId: "adjust_user_123",
amplitudeUserId: "amp_456",
mixpanelDistinctId: "mix_789",
});
}, []);
return <YourApp />;
}
Supported Integrations
Superwall supports the following third-party integrations:Attribution Platforms
- Adjust
- AppsFlyer
- Kochava
- Tenjin
import Adjust from "react-native-adjust";
import { useUser } from "expo-superwall";
function App() {
const { setIntegrationAttributes } = useUser();
useEffect(() => {
// Get Adjust ID
Adjust.getAdid((adid) => {
setIntegrationAttributes({
adjustId: adid,
});
});
}, []);
}
import appsFlyer from "react-native-appsflyer";
import { useUser } from "expo-superwall";
function App() {
const { setIntegrationAttributes } = useUser();
useEffect(() => {
// Get AppsFlyer ID
appsFlyer.getAppsFlyerUID((error, uid) => {
if (!error) {
setIntegrationAttributes({
appsflyerId: uid,
});
}
});
}, []);
}
import { useUser } from "expo-superwall";
function App() {
const { setIntegrationAttributes } = useUser();
useEffect(() => {
// Get Kochava device ID
const kochavaId = getKochavaDeviceId(); // Your Kochava SDK method
setIntegrationAttributes({
kochavaDeviceId: kochavaId,
});
}, []);
}
import { useUser } from "expo-superwall";
function App() {
const { setIntegrationAttributes } = useUser();
useEffect(() => {
// Get Tenjin ID
const tenjinId = getTenjinId(); // Your Tenjin SDK method
setIntegrationAttributes({
tenjinId: tenjinId,
});
}, []);
}
Analytics Platforms
- Amplitude
- Mixpanel
- PostHog
- mParticle
import { Amplitude } from "@amplitude/react-native";
import { useUser } from "expo-superwall";
function App() {
const { setIntegrationAttributes } = useUser();
useEffect(() => {
const amplitude = Amplitude.getInstance();
setIntegrationAttributes({
amplitudeDeviceId: amplitude.getDeviceId(),
amplitudeUserId: amplitude.getUserId(),
});
}, []);
}
import { Mixpanel } from "mixpanel-react-native";
import { useUser } from "expo-superwall";
function App() {
const { setIntegrationAttributes } = useUser();
useEffect(() => {
const mixpanel = new Mixpanel("YOUR_TOKEN");
// Get distinct ID
mixpanel.getDistinctId().then((distinctId) => {
setIntegrationAttributes({
mixpanelDistinctId: distinctId,
});
});
}, []);
}
import { usePostHog } from "posthog-react-native";
import { useUser } from "expo-superwall";
function App() {
const posthog = usePostHog();
const { setIntegrationAttributes } = useUser();
useEffect(() => {
if (posthog) {
setIntegrationAttributes({
posthogUserId: posthog.getDistinctId(),
});
}
}, [posthog]);
}
import MParticle from "react-native-mparticle";
import { useUser } from "expo-superwall";
function App() {
const { setIntegrationAttributes } = useUser();
useEffect(() => {
// Get mParticle ID
const mpid = MParticle.User.getCurrentUser().getMPID();
setIntegrationAttributes({
mparticleId: mpid,
});
}, []);
}
Marketing & Engagement
- Braze
- OneSignal
- Airship
- Customer.io
- Iterable
import Braze from "react-native-appboy-sdk";
import { useUser } from "expo-superwall";
function App() {
const { setIntegrationAttributes } = useUser();
useEffect(() => {
setIntegrationAttributes({
brazeAliasName: "user_alias",
brazeAliasLabel: "user_label",
});
}, []);
}
import OneSignal from "react-native-onesignal";
import { useUser } from "expo-superwall";
function App() {
const { setIntegrationAttributes } = useUser();
useEffect(() => {
OneSignal.getDeviceState().then((deviceState) => {
if (deviceState?.userId) {
setIntegrationAttributes({
onesignalId: deviceState.userId,
});
}
});
}, []);
}
import { useUser } from "expo-superwall";
function App() {
const { setIntegrationAttributes } = useUser();
useEffect(() => {
// Get Airship channel ID
const channelId = getAirshipChannelId(); // Your Airship SDK method
setIntegrationAttributes({
airshipChannelId: channelId,
});
}, []);
}
import { useUser } from "expo-superwall";
function App() {
const { setIntegrationAttributes } = useUser();
useEffect(() => {
// Set Customer.io ID
setIntegrationAttributes({
customerioId: "customer_123",
});
}, []);
}
import { useUser } from "expo-superwall";
function App() {
const { setIntegrationAttributes } = useUser();
useEffect(() => {
setIntegrationAttributes({
iterableUserId: "iterable_user_123",
iterableCampaignId: "campaign_456",
iterableTemplateId: "template_789",
});
}, []);
}
Other Platforms
- Firebase
- Facebook
- CleverTap
import analytics from "@react-native-firebase/analytics";
import { useUser } from "expo-superwall";
function App() {
const { setIntegrationAttributes } = useUser();
useEffect(() => {
analytics().getAppInstanceId().then((instanceId) => {
setIntegrationAttributes({
firebaseAppInstanceId: instanceId,
});
});
}, []);
}
import { useUser } from "expo-superwall";
function App() {
const { setIntegrationAttributes } = useUser();
useEffect(() => {
// Get Facebook anonymous ID
const fbAnonId = getFacebookAnonId(); // Your implementation
setIntegrationAttributes({
fbAnonId: fbAnonId,
});
}, []);
}
import { useUser } from "expo-superwall";
function App() {
const { setIntegrationAttributes } = useUser();
useEffect(() => {
// Get CleverTap ID
const clevertapId = getCleverTapId(); // Your CleverTap SDK method
setIntegrationAttributes({
clevertapId: clevertapId,
});
}, []);
}
Available Attributes
Here are all the supported integration attributes:type IntegrationAttributes = {
adjustId?: string; // Adjust attribution
amplitudeDeviceId?: string; // Amplitude device ID
amplitudeUserId?: string; // Amplitude user ID
appsflyerId?: string; // AppsFlyer ID
brazeAliasName?: string; // Braze alias name
brazeAliasLabel?: string; // Braze alias label
onesignalId?: string; // OneSignal player ID
fbAnonId?: string; // Facebook anonymous ID
firebaseAppInstanceId?: string; // Firebase app instance ID
iterableUserId?: string; // Iterable user ID
iterableCampaignId?: string; // Iterable campaign ID
iterableTemplateId?: string; // Iterable template ID
mixpanelDistinctId?: string; // Mixpanel distinct ID
mparticleId?: string; // mParticle ID
clevertapId?: string; // CleverTap ID
airshipChannelId?: string; // Airship channel ID
kochavaDeviceId?: string; // Kochava device ID
tenjinId?: string; // Tenjin ID
posthogUserId?: string; // PostHog user ID
customerioId?: string; // Customer.io ID
};
Getting Integration Attributes
Retrieve currently set integration attributes:import { useUser } from "expo-superwall";
function DebugScreen() {
const { getIntegrationAttributes } = useUser();
const showAttributes = async () => {
const attributes = await getIntegrationAttributes();
console.log("Integration attributes:", attributes);
// { adjustId: "...", amplitudeUserId: "..." }
};
return <Button title="Show Attributes" onPress={showAttributes} />;
}
Complete Example
Here’s a complete setup with multiple integrations:import { useUser } from "expo-superwall";
import { useEffect } from "react";
import { Amplitude } from "@amplitude/react-native";
import appsFlyer from "react-native-appsflyer";
import { Mixpanel } from "mixpanel-react-native";
import OneSignal from "react-native-onesignal";
import analytics from "@react-native-firebase/analytics";
function IntegrationSetup() {
const { setIntegrationAttributes } = useUser();
useEffect(() => {
setupIntegrations();
}, []);
const setupIntegrations = async () => {
try {
// Collect all integration IDs
const attributes: Record<string, string> = {};
// Amplitude
const amplitude = Amplitude.getInstance();
attributes.amplitudeDeviceId = amplitude.getDeviceId();
attributes.amplitudeUserId = amplitude.getUserId();
// AppsFlyer
const appsflyerId = await new Promise<string>((resolve) => {
appsFlyer.getAppsFlyerUID((error, uid) => {
resolve(uid || "");
});
});
if (appsflyerId) {
attributes.appsflyerId = appsflyerId;
}
// Mixpanel
const mixpanel = new Mixpanel("YOUR_TOKEN");
const mixpanelId = await mixpanel.getDistinctId();
if (mixpanelId) {
attributes.mixpanelDistinctId = mixpanelId;
}
// OneSignal
const deviceState = await OneSignal.getDeviceState();
if (deviceState?.userId) {
attributes.onesignalId = deviceState.userId;
}
// Firebase
const firebaseId = await analytics().getAppInstanceId();
if (firebaseId) {
attributes.firebaseAppInstanceId = firebaseId;
}
// Set all attributes at once
await setIntegrationAttributes(attributes);
console.log("Integration attributes set:", Object.keys(attributes));
} catch (error) {
console.error("Failed to set integration attributes:", error);
}
};
return null;
}
export default IntegrationSetup;
Best Practices
Set attributes early in app lifecycle
Set attributes early in app lifecycle
Set integration attributes as soon as possible, ideally right after SDK initialization:
useEffect(() => {
if (user) {
setIntegrationAttributes({ /* ... */ });
}
}, [user]);
Wait for third-party SDKs to initialize
Wait for third-party SDKs to initialize
Make sure analytics SDKs are initialized before getting their IDs:
const setupIntegrations = async () => {
// Wait for Amplitude to be ready
await amplitude.init("API_KEY");
// Then set attributes
await setIntegrationAttributes({
amplitudeUserId: amplitude.getUserId(),
});
};
Handle errors gracefully
Handle errors gracefully
Wrap attribute collection in try-catch blocks:
try {
const appsflyerId = await getAppsFlyerId();
await setIntegrationAttributes({ appsflyerId });
} catch (error) {
console.error("Failed to get AppsFlyer ID:", error);
// Continue without it
}
Update when IDs change
Update when IDs change
Re-set integration attributes when user IDs change (e.g., after login):
const handleLogin = async (userId: string) => {
await identify(userId);
// Update analytics IDs
await amplitude.setUserId(userId);
// Sync with Superwall
await setIntegrationAttributes({
amplitudeUserId: userId,
});
};
Only set relevant platforms
Only set relevant platforms
Only include platforms you actually use:
// ✅ Good - only includes used platforms
setIntegrationAttributes({
amplitudeUserId: "...",
mixpanelDistinctId: "...",
});
// ❌ Bad - includes platforms not in use
setIntegrationAttributes({
amplitudeUserId: "...",
adjustId: undefined,
appsflyerId: undefined,
// ...
});
Use Cases
Cross-Platform Attribution
Link Superwall subscription events to attribution campaigns:import { useUser, useSuperwallEvents } from "expo-superwall";
import appsFlyer from "react-native-appsflyer";
function AttributionTracking() {
const { setIntegrationAttributes } = useUser();
useEffect(() => {
// Set AppsFlyer ID
appsFlyer.getAppsFlyerUID((error, uid) => {
if (!error) {
setIntegrationAttributes({ appsflyerId: uid });
}
});
}, []);
// Track subscription events in AppsFlyer
useSuperwallEvents({
onPaywallDismiss: (info, result) => {
if (result.type === "purchased") {
appsFlyer.logEvent("af_purchase", {
af_revenue: "9.99",
af_currency: "USD",
af_content_id: result.productId,
});
}
},
});
return null;
}
Unified Analytics
Connect Superwall events with your analytics platforms:import { useSuperwallEvents } from "expo-superwall";
import { Amplitude } from "@amplitude/react-native";
function AnalyticsSync() {
const amplitude = Amplitude.getInstance();
useSuperwallEvents({
onPaywallPresent: (info) => {
amplitude.logEvent("paywall_viewed", {
paywall_id: info.identifier,
paywall_name: info.name,
});
},
onPaywallDismiss: (info, result) => {
amplitude.logEvent("paywall_dismissed", {
paywall_id: info.identifier,
result_type: result.type,
});
},
});
return null;
}
Next Steps
Managing Users
Learn about user identification and attributes
Handling Subscriptions
Track subscription status and entitlements