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: 'john@example.com',
  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

Basic HTML content rendering (for full HTML support, consider using react-native-render-html).

Properties:

  • content - HTML content (simplified rendering - strips tags and displays text)

Note: For full HTML rendering, you can enhance the HtmlBlock component to use react-native-render-html.

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: 'john@example.com',
      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.