Examples
Real-world examples of using the Tappd Mobile SDK in React Native applications.
E-commerce
Product Purchase Flow
javascript
import TappdSDK from '@tappd/mobile-sdk';
const tappd = new TappdSDK({ appId: 'YOUR_APP_ID' });
// 1. User views product
await tappd.track('ecommerce.product_viewed', {
productId: 'prod_123',
productName: 'iPhone 15',
category: 'Electronics',
price: 999.00,
currency: 'USD'
});
// 2. User adds to cart
await tappd.track('ecommerce.add_to_cart', {
productId: 'prod_123',
productName: 'iPhone 15',
quantity: 1,
price: 999.00,
currency: 'USD'
});
// 3. User starts checkout
await tappd.track('ecommerce.checkout_started', {
cartValue: 999.00,
currency: 'USD'
});
// 4. User completes purchase
await tappd.track('ecommerce.purchase', {
orderId: 'ord_456',
total: 999.00,
currency: 'USD',
items: [{
productId: 'prod_123',
name: 'iPhone 15',
price: 999.00,
quantity: 1
}]
});User Authentication
Sign Up Flow
javascript
async function handleSignUp(email, name) {
// Track signup attempt
await tappd.track('user.signup.started', {
method: 'email'
});
try {
// Create user account
const user = await createAccount(email, name);
// Identify user (merges anonymous data)
await tappd.identify({
external_id: user.id, // Your internal user ID
email: email,
name: name,
signupDate: new Date().toISOString()
});
// Track successful signup
await tappd.track('user.signup.completed', {
method: 'email'
// Note: userId not needed - SDK automatically associates event with identified user
});
} catch (error) {
// Track signup failure
await tappd.track('user.signup.failed', {
method: 'email',
error: error.message
});
}
}Login Flow
javascript
async function handleLogin(email) {
// Track login attempt
await tappd.track('user.login.started', {
method: 'email'
});
try {
const user = await authenticate(email);
// Identify user
await tappd.identify({
external_id: user.id, // Your internal user ID
email: user.email,
name: user.name,
lastLogin: new Date().toISOString()
});
// Track successful login
await tappd.track('user.login.completed', {
method: 'email'
// Note: userId not needed - SDK automatically associates event with identified user
});
} catch (error) {
// Track login failure
await tappd.track('user.login.failed', {
method: 'email',
error: error.message
});
}
}Logout
javascript
function handleLogout() {
// Track logout
tappd.track('user.logout');
// Reset SDK (clears user data)
tappd.reset();
}Screen Tracking
With React Navigation
javascript
import React from 'react';
import { View, Text } from 'react-native';
import { useFocusEffect } from '@react-navigation/native';
import { useTappd } from '../contexts/TappdContext';
function ProductScreen({ route }) {
const tappd = useTappd();
const { productId } = route.params;
useFocusEffect(
React.useCallback(() => {
tappd.trackScreen('ProductScreen', {
productId: productId,
category: 'ecommerce'
});
}, [productId])
);
return (
<View>
<Text>Product Screen</Text>
</View>
);
}Manual Screen Tracking
javascript
import { useEffect } from 'react';
function MyScreen() {
const tappd = useTappd();
useEffect(() => {
tappd.trackScreen('MyScreen', {
category: 'main',
section: 'dashboard'
});
}, []);
return (
// Screen content
);
}Push Notifications
Complete Push Setup
javascript
import React, { useEffect } from 'react';
import messaging from '@react-native-firebase/messaging';
import { Platform } from 'react-native';
import TappdSDK from '@tappd/mobile-sdk';
const tappd = new TappdSDK({ appId: 'YOUR_APP_ID' });
function App() {
useEffect(() => {
setupPushNotifications();
}, []);
async function setupPushNotifications() {
try {
// Request permission
if (Platform.OS === 'ios') {
const authStatus = await messaging().requestPermission();
const enabled =
authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
authStatus === messaging.AuthorizationStatus.PROVISIONAL;
if (!enabled) return;
}
// Get token
const token = await messaging().getToken();
if (token) {
// User must be identified first
await tappd.identify({
external_id: 'user_123',
email: 'john@example.com'
});
// Register token
await tappd.registerPushToken(
token,
Platform.OS === 'ios' ? 'ios' : 'android'
);
}
// Listen for token refresh
messaging().onTokenRefresh(async (newToken) => {
await tappd.registerPushToken(
newToken,
Platform.OS === 'ios' ? 'ios' : 'android'
);
});
// Handle foreground messages
messaging().onMessage(async (remoteMessage) => {
await tappd.track('push_notification.received', {
notificationId: remoteMessage.messageId,
title: remoteMessage.notification?.title
});
});
// Handle notification opens
messaging().onNotificationOpenedApp(async (remoteMessage) => {
await tappd.track('push_notification.opened', {
notificationId: remoteMessage.messageId
});
});
} catch (error) {
console.error('Push setup failed:', error);
}
}
return (
// Your app
);
}Subscription Management
Subscription Upgrade
javascript
async function handleUpgrade(newPlan, userId) {
const currentPlan = getUserPlan();
await tappd.track('subscription.upgrade', {
fromPlan: currentPlan,
toPlan: newPlan,
upgradeDate: new Date().toISOString()
});
// Update user attributes (requires external_id)
// Note: external_id must match the one used in identify()
await tappd.setUserAttributes({
external_id: userId, // Required: Must match the external_id from identify()
plan: newPlan,
upgradedAt: new Date().toISOString()
});
}Subscription Cancellation
javascript
async function handleCancellation(reason, userId) {
await tappd.track('subscription.cancelled', {
reason: reason,
cancelledAt: new Date().toISOString()
});
await tappd.setUserAttributes({
external_id: userId, // Required: Must match the external_id from identify()
planStatus: 'cancelled',
cancellationDate: new Date().toISOString()
});
}App Lifecycle
Track App State Changes
javascript
import { AppState } from 'react-native';
import { useEffect } from 'react';
function App() {
useEffect(() => {
const subscription = AppState.addEventListener('change', (nextAppState) => {
if (nextAppState === 'active') {
// App came to foreground
tappd.track('app.foreground');
} else if (nextAppState === 'background') {
// App went to background
tappd.track('app.background');
tappd.cleanup(); // Cleanup on background
}
});
return () => {
subscription.remove();
};
}, []);
return (
// Your app
);
}Button Tracking
Track Button Clicks
javascript
import { TouchableOpacity, Text } from 'react-native';
import { useTappd } from '../contexts/TappdContext';
function MyButton({ buttonId, title, onPress }) {
const tappd = useTappd();
const handlePress = async () => {
// Track button click
await tappd.track('button_click', {
buttonId: buttonId,
buttonText: title,
location: 'home_screen'
});
// Execute original onPress
if (onPress) onPress();
};
return (
<TouchableOpacity onPress={handlePress}>
<Text>{title}</Text>
</TouchableOpacity>
);
}
// Usage
<MyButton
buttonId="signup_button"
title="Sign Up"
onPress={() => navigation.navigate('SignUp')}
/>Form Tracking
Track Form Interactions
javascript
import { useState } from 'react';
import { TextInput, Button } from 'react-native';
import { useTappd } from '../contexts/TappdContext';
function SignUpForm() {
const tappd = useTappd();
const [formData, setFormData] = useState({});
const handleFieldFocus = async (fieldName) => {
await tappd.track('form.field_focused', {
formId: 'signup_form',
fieldName: fieldName
});
};
const handleSubmit = async () => {
// Track form submission
await tappd.track('form.submitted', {
formId: 'signup_form',
formName: 'Sign Up',
fieldsCompleted: Object.keys(formData).length
});
// Submit form
await submitForm(formData);
};
return (
<>
<TextInput
placeholder="Email"
onFocus={() => handleFieldFocus('email')}
onChangeText={(text) => setFormData({ ...formData, email: text })}
/>
<Button title="Submit" onPress={handleSubmit} />
</>
);
}Context Provider Pattern
Create Tappd Context
javascript
// contexts/TappdContext.js
import React, { createContext, useContext, useState, useEffect } from 'react';
import TappdSDK from '@tappd/mobile-sdk';
const TappdContext = createContext(null);
export function TappdProvider({ children, appId }) {
const [tappd] = useState(() => {
return new TappdSDK({
appId: appId,
debug: __DEV__
});
});
useEffect(() => {
// Cleanup on unmount
return () => {
tappd.cleanup();
};
}, []);
return (
<TappdContext.Provider value={tappd}>
{children}
</TappdContext.Provider>
);
}
export function useTappd() {
const context = useContext(TappdContext);
if (!context) {
throw new Error('useTappd must be used within TappdProvider');
}
return context;
}Use in App
javascript
// App.js
import { TappdProvider } from './contexts/TappdContext';
function App() {
return (
<TappdProvider appId="YOUR_APP_ID">
{/* Your app components */}
</TappdProvider>
);
}Error Tracking
Track Errors
javascript
import { ErrorUtils } from 'react-native';
// Set up global error handler
ErrorUtils.setGlobalHandler(async (error, isFatal) => {
try {
await tappd.track('error', {
message: error.message,
stack: error.stack,
isFatal: isFatal,
timestamp: new Date().toISOString()
});
} catch (trackingError) {
console.error('Failed to track error:', trackingError);
}
// Call default handler
if (ErrorUtils.getGlobalHandler) {
ErrorUtils.getGlobalHandler()(error, isFatal);
}
});Deep Linking
Track Deep Link Opens
javascript
import { Linking } from 'react-native';
import { useEffect } from 'react';
import { useTappd } from '../contexts/TappdContext';
function App() {
const tappd = useTappd();
useEffect(() => {
// Get initial URL
Linking.getInitialURL().then((url) => {
if (url) {
tappd.track('deep_link.opened', {
url: url,
source: 'cold_start'
});
}
});
// Listen for deep links
const subscription = Linking.addEventListener('url', (event) => {
tappd.track('deep_link.opened', {
url: event.url,
source: 'warm_start'
});
});
return () => {
subscription.remove();
};
}, []);
return (
// Your app
);
}Next Steps
- API Reference - Complete method documentation
- Push Notifications - Push notification setup
- React Navigation - Navigation integration
- Troubleshooting - Common issues and solutions
