Skip to content

In-App Messages ​

The Tappd Mobile SDK supports displaying in-app messages (banners, popups, and modals) created in your Tappd dashboard. Messages are automatically fetched and displayed when enabled, and you can integrate them into your React Native app using the provided components.

Overview ​

In-app messages allow you to:

  • Display personalized messages to users based on their behavior
  • Show banners at the top or bottom of the screen
  • Display popups and modals with rich content
  • Track message views, clicks, and dismissals
  • Automatically evaluate trigger conditions and expiration dates

Configuration ​

Enable in-app messages when initializing the SDK:

javascript
const tappd = new TappdSDK({
  appId: 'YOUR_APP_ID',
  apiUrl: 'https://sdk.gotappd.com/api/v1/sdk',
  enableInAppMessages: true,        // Enable in-app message rendering (default: true)
  autoDisplayMessages: true,        // Automatically display pending messages (default: true)
  messagePollingInterval: 30,       // Poll for new messages every 30 seconds (default: 30)
});

Configuration Options ​

OptionTypeDefaultDescription
enableInAppMessagesbooleantrueEnable/disable in-app message rendering
autoDisplayMessagesbooleantrueAutomatically fetch and display pending messages
messagePollingIntervalnumber30Interval in seconds for polling new messages

React Native Integration ​

To render messages in your React Native app, you need to set up a render callback that displays the message components.

Basic Setup ​

javascript
import React, { useState, useEffect } from 'react';
import { View } from 'react-native';
import TappdSDK from '@tappd/mobile-sdk';
import { MessageRenderer } from '@tappd/mobile-sdk/src/renderers/MessageRenderer';
import type { InAppMessage } from '@tappd/mobile-sdk/src/types/inAppMessage';

const tappd = new TappdSDK({
  appId: 'YOUR_APP_ID',
  enableInAppMessages: true,
  autoDisplayMessages: true
});

function App() {
  const [currentMessage, setCurrentMessage] = useState<InAppMessage | null>(null);

  useEffect(() => {
    // Set callback for rendering messages
    tappd.setMessageRenderCallback((message: InAppMessage) => {
      setCurrentMessage(message);
    });
  }, []);

  const handleDismiss = async (messageId: string) => {
    await tappd.dismissMessage(messageId);
    setCurrentMessage(null);
  };

  const handleButtonClick = async (messageId: string, link: string, text: string) => {
    // Handle button click (e.g., navigation)
    console.log('Button clicked:', link);
    await handleDismiss(messageId);
  };

  return (
    <View style={{ flex: 1 }}>
      {/* Your app content */}
      
      {/* Render in-app message */}
      {currentMessage && (
        <MessageRenderer
          message={currentMessage}
          onDismiss={handleDismiss}
          onButtonClick={handleButtonClick}
        />
      )}
    </View>
  );
}

Automatic Display ​

When autoDisplayMessages is enabled, the SDK will:

  1. Automatically fetch pending messages for the identified user
  2. Evaluate trigger conditions (immediate, delay, event-based)
  3. Call the render callback for messages that are ready to be shown
  4. Track events (viewed, clicked, dismissed)
  5. Poll periodically for new messages (based on messagePollingInterval)
javascript
const tappd = new TappdSDK({
  appId: 'YOUR_APP_ID',
  enableInAppMessages: true,
  autoDisplayMessages: true,
  messagePollingInterval: 30  // Check for new messages every 30 seconds
});

// Identify user - messages will be fetched automatically
await tappd.identify({
  external_id: 'user_123',
  email: '[email protected]',
  name: 'John Doe'
});

// Set render callback to display messages
tappd.setMessageRenderCallback((message) => {
  // Display the message in your UI
  setCurrentMessage(message);
});

Manual Control ​

You can also manually control message fetching and display:

Fetch Messages ​

javascript
// Fetch all pending messages for the current user
const messages = await tappd.getInAppMessages();
console.log(`Found ${messages.length} pending messages`);

Display a Specific Message ​

javascript
const messages = await tappd.getInAppMessages();

// Display the first message
if (messages.length > 0) {
  await tappd.displayInAppMessage(messages[0]);
}

Display All Pending Messages ​

javascript
// Fetch and display all pending messages
await tappd.displayPendingMessages();

Dismiss a Message ​

javascript
// Dismiss a message by its ID
await tappd.dismissMessage('message_id_123');

Message Types ​

The SDK supports three message types, each rendered as React Native components:

1. Banner ​

Banners are fixed-position messages that appear at the top or bottom of the screen using absolute positioning.

  • Position: Top or bottom
  • Dismissible: Can include a dismiss button
  • Animation: Slide animation
  • Use cases: Important announcements, notifications, promotions

2. Popup ​

Popups are centered modal dialogs with an optional overlay using React Native's Modal component.

  • Size: Smaller modal (typically 90% of screen width, max 500px)
  • Overlay: Optional semi-transparent background overlay
  • Close button: Optional close button
  • Animation: Fade or scale animation
  • Use cases: Important alerts, confirmations, CTAs

3. Modal ​

Modals are larger centered modal dialogs, similar to popups but with more space.

  • Size: Larger modal (typically 85% of screen width, max 600px)
  • Overlay: Optional semi-transparent background overlay
  • Close button: Optional close button
  • Animation: Fade or scale animation
  • Use cases: Detailed information, forms, multi-step flows

Message Blocks ​

Messages can contain multiple content blocks rendered as React Native components:

Image Block ​

Display images using React Native's Image component.

Properties:

  • url - Image URL
  • alt - Alt text for accessibility
  • width - Image width
  • height - Image height
  • alignment - left, center, right, or full

Text Block ​

Display text content using React Native's Text component.

Properties:

  • content - Text content
  • fontSize - sm, base, lg, xl, 2xl, or custom size
  • fontWeight - normal or bold
  • color - Text color (hex, rgb, or named color)
  • alignment - left, center, right, or justify

Button Block ​

Clickable buttons using React Native's TouchableOpacity or Pressable.

Properties:

  • text - Button text
  • link - URL to navigate to (uses Linking.openURL())
  • textColor - Button text color
  • backgroundColor - Button background color
  • linkBehavior - browser (open URL), in_app, or deeplink
  • alignment - left, center, or right

HTML Block ​

HTML content rendering (bundled via react-native-render-html in the SDK).

Properties:

  • content - HTML content to render (full HTML supported via react-native-render-html, which is bundled with the mobile SDK).

Behavior notes:

  • HTML blocks are rendered using the same in-app message delivery rules described above (expiration, triggers, and single-display guarantees).
  • Because the renderer is packaged inside the SDK, you do not need to install react-native-render-html in your app separately.

Event Tracking ​

The SDK automatically tracks message interactions:

Message Viewed ​

Tracked when a message is displayed:

javascript
// Automatically tracked by SDK
// Event: message.viewed
// Properties: { messageId: '...' }

Message Clicked ​

Tracked when a button in a message is clicked:

javascript
// Automatically tracked by SDK
// Event: message.clicked
// Properties: { messageId: '...', buttonText: '...', buttonLink: '...' }

Message Dismissed ​

Tracked when a message is dismissed:

javascript
// Automatically tracked by SDK
// Event: message.dismissed
// Properties: { messageId: '...' }

Manual Event Tracking ​

You can also manually track message events:

javascript
await tappd.trackMessageEvent('message_id_123', 'clicked', {
  buttonText: 'Sign Up',
  buttonLink: 'https://example.com/signup'
});

API Reference ​

setMessageRenderCallback(callback) ​

Set a callback function that will be called when a message should be displayed.

Parameters:

ParameterTypeRequiredDescription
callback(message: InAppMessage) => voidYesFunction called with the message to display

Returns: void

Example:

javascript
tappd.setMessageRenderCallback((message) => {
  setCurrentMessage(message);
});

getInAppMessages() ​

Fetch pending in-app messages for the current user.

Returns: Promise<InAppMessage[]>

Example:

javascript
const messages = await tappd.getInAppMessages();
messages.forEach(message => {
  console.log(`Message: ${message.config.messageType}`);
  console.log(`Status: ${message.status}`);
});

displayInAppMessage(message) ​

Display a specific in-app message. This will call the render callback if set.

Parameters:

ParameterTypeRequiredDescription
messageInAppMessageYesThe message object to display

Returns: Promise<void>

Example:

javascript
const messages = await tappd.getInAppMessages();
if (messages.length > 0) {
  await tappd.displayInAppMessage(messages[0]);
}

displayPendingMessages() ​

Fetch and display all pending messages that are ready to be shown.

Returns: Promise<void>

Example:

javascript
// Manually trigger message display
await tappd.displayPendingMessages();

dismissMessage(messageId) ​

Dismiss a message and track the dismissal event.

Parameters:

ParameterTypeRequiredDescription
messageIdstringYesThe ID of the message to dismiss

Returns: Promise<void>

Example:

javascript
await tappd.dismissMessage('message_id_123');

trackMessageEvent(messageId, eventType, metadata) ​

Track a custom message interaction event.

Parameters:

ParameterTypeRequiredDescription
messageIdstringYesThe ID of the message
eventTypestringYesEvent type (e.g., 'viewed', 'clicked', 'dismissed')
metadataobjectNoAdditional event metadata

Returns: Promise<void>

Example:

javascript
await tappd.trackMessageEvent('message_id_123', 'clicked', {
  buttonText: 'Get Started',
  buttonLink: '/signup'
});

Complete Example ​

Here's a complete example showing how to integrate in-app messages in a React Native app:

javascript
import React, { useState, useEffect } from 'react';
import { View, StyleSheet } from 'react-native';
import TappdSDK from '@tappd/mobile-sdk';
import { MessageRenderer } from '@tappd/mobile-sdk/src/renderers/MessageRenderer';
import type { InAppMessage } from '@tappd/mobile-sdk/src/types/inAppMessage';

// Initialize SDK with in-app messages enabled
const tappd = new TappdSDK({
  appId: 'YOUR_APP_ID',
  apiUrl: 'https://sdk.gotappd.com/api/v1/sdk',
  enableInAppMessages: true,
  autoDisplayMessages: true,
  messagePollingInterval: 30,
  debug: true
});

export default function App() {
  const [currentMessage, setCurrentMessage] = useState<InAppMessage | null>(null);

  useEffect(() => {
    // Set callback for rendering messages
    tappd.setMessageRenderCallback((message: InAppMessage) => {
      setCurrentMessage(message);
    });

    // Identify user - messages will be fetched automatically
    tappd.identify({
      external_id: 'user_123',
      email: '[email protected]',
      name: 'John Doe'
    });

    return () => {
      // Cleanup
      tappd.setMessageRenderCallback(() => {});
    };
  }, []);

  const handleDismiss = async (messageId: string) => {
    await tappd.dismissMessage(messageId);
    setCurrentMessage(null);
  };

  const handleButtonClick = async (
    messageId: string,
    link: string,
    text: string
  ) => {
    // Handle button click - you can navigate, open URL, etc.
    console.log('Button clicked:', { messageId, link, text });
    
    // Example: Open URL
    if (link && link !== '#') {
      Linking.openURL(link);
    }
    
    // Dismiss message after handling click
    await handleDismiss(messageId);
  };

  return (
    <View style={styles.container}>
      {/* Your app content */}
      
      {/* Render in-app message */}
      {currentMessage && (
        <MessageRenderer
          message={currentMessage}
          onDismiss={handleDismiss}
          onButtonClick={handleButtonClick}
        />
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
});

Integration with React Navigation ​

You can integrate messages with React Navigation by displaying them at the root level:

javascript
import { NavigationContainer } from '@react-navigation/native';
import TappdSDK from '@tappd/mobile-sdk';
import { MessageRenderer } from '@tappd/mobile-sdk/src/renderers/MessageRenderer';

function App() {
  const [currentMessage, setCurrentMessage] = useState(null);

  useEffect(() => {
    tappd.setMessageRenderCallback((message) => {
      setCurrentMessage(message);
    });
  }, []);

  return (
    <NavigationContainer>
      {/* Your navigation structure */}
      
      {/* Messages displayed at root level */}
      {currentMessage && (
        <MessageRenderer
          message={currentMessage}
          onDismiss={(id) => {
            tappd.dismissMessage(id);
            setCurrentMessage(null);
          }}
        />
      )}
    </NavigationContainer>
  );
}

Styling ​

Message components use React Native StyleSheet for styling. You can customize styles by:

  1. Modifying the component styles - Edit the styles in MessageRenderer.tsx and BlockRenderer.tsx
  2. Using theme providers - Wrap message components with your theme provider
  3. Platform-specific styles - Use Platform.OS for iOS/Android specific styling

Best Practices ​

  1. Identify users early: Make sure to call identify() as soon as users log in so messages can be personalized
  2. Set render callback: Always set the render callback in your app's root component
  3. Handle navigation: Implement proper navigation logic in button click handlers
  4. Monitor message performance: Use the tracked events to measure message effectiveness
  5. Test on both platforms: Test messages on both iOS and Android devices
  6. Handle app state: Consider pausing message display when app goes to background

Troubleshooting ​

Messages not displaying ​

  1. Check that enableInAppMessages is set to true
  2. Verify the render callback is set using setMessageRenderCallback()
  3. Verify the user is identified (identify() has been called)
  4. Check console for errors (enable debug: true)
  5. Verify messages exist in the dashboard and are published
  6. Check trigger conditions are met

Messages displaying too frequently ​

  1. Adjust messagePollingInterval to reduce polling frequency
  2. Check message expiration settings in the dashboard
  3. Ensure messages are being dismissed properly

Styling issues ​

  1. Check for style conflicts with your app's styles
  2. Ensure message components are rendered at the correct level in the component tree
  3. Test on both iOS and Android as styles may differ

Released under the MIT License.