Skip to content

In-App Message Bridge

The Tappd In-App Message Bridge provides a powerful way to handle user interactions with in-app messages. It allows you to track events, update customer profiles, capture form data, and perform actions when users interact with your in-app messages.

Overview

The Bridge API enables two-way communication between your in-app messages and the Tappd backend:

  • Button Actions: Handle clicks on buttons in messages (close, track events, update profiles, open links)
  • Form Capture: Capture and process form submissions from in-app messages
  • Customer Management: Automatically find or create customers based on identifiers
  • Event Tracking: Track custom events with properties from user interactions
  • Profile Updates: Update customer attributes from button clicks or form submissions

How It Works

When a user interacts with an in-app message:

  1. The SDK captures the interaction (button click or form submission)
  2. It sends a request to the Bridge API endpoint with the interaction data
  3. The backend processes the action (track event, update profile, etc.)
  4. The customer is automatically identified and linked to the action

Button Actions

Buttons in in-app messages can perform various actions when clicked. These are configured in the message editor in your Tappd dashboard.

Supported Action Types

Close Message

Closes the message when the button is clicked:

javascript
// Configured in dashboard - action type: "close"
// No additional configuration needed

Track Event

Tracks a custom event when the button is clicked:

javascript
// Configured in dashboard:
// Action type: "track_event"
// Event name: "button_clicked"
// Event properties: { source: "promo_banner", campaign: "summer_sale" }

Bridge Request:

POST /api/v1/sdk/bridge/action
Content-Type: application/json
X-App-Id: YOUR_APP_ID

{
  "messageId": "msg_123",
  "actionType": "track_event",
  "actionData": {
    "eventName": "button_clicked",
    "eventProperties": {
      "source": "promo_banner",
      "campaign": "summer_sale"
    }
  },
  "userId": "user_123",
  "external_id": "ext_123",
  "email": "user@example.com"
}

Response:

{
  "success": true,
  "message": "Bridge action processed",
  "data": {
    "eventId": "event_456"
  }
}

Update Customer Profile

Updates customer attributes when the button is clicked:

javascript
// Configured in dashboard:
// Action type: "update_profile"
// Profile attributes: { 
//   "user_segment": "premium",
//   "last_promotion_viewed": "summer_sale"
// }

Bridge Request:

POST /api/v1/sdk/bridge/action
Content-Type: application/json
X-App-Id: YOUR_APP_ID

{
  "messageId": "msg_123",
  "actionType": "update_profile",
  "actionData": {
    "profileAttributes": {
      "user_segment": "premium",
      "last_promotion_viewed": "summer_sale"
    }
  },
  "userId": "user_123",
  "external_id": "ext_123"
}

Response:

{
  "success": true,
  "message": "Bridge action processed",
  "data": {
    "updated": true,
    "attributes": ["user_segment", "last_promotion_viewed"]
  }
}

Opens a URL when the button is clicked (handled client-side):

javascript
// Configured in dashboard:
// Action type: "link"
// Link: "https://example.com/promo"
// Link behavior: "browser" (new tab) or "same_window"

The link action is handled entirely in the browser - the SDK opens the link without making a bridge API call.

Combining Actions with Form Data

Button actions can also include form data if the button is inside a form block:

javascript
// When button is clicked in a form, formData is automatically included
{
  "messageId": "msg_123",
  "actionType": "track_event",
  "actionData": {
    "eventName": "newsletter_signup",
    "eventProperties": {}
  },
  "formData": {
    "email": "user@example.com",
    "name": "John Doe",
    "newsletter": "true"
  }
}

Form Data Capture

Forms in in-app messages can capture user input and automatically process it using submit actions.

Form Submit Actions

When a form is submitted, you can configure what happens to the data:

Track Event

Create an event with form data as event properties:

javascript
// Configured in dashboard:
// Submit action type: "track_event"
// Event name: "newsletter_signup"
// Event properties mapping: {
//   "email_address": "email",  // Maps form field "email" to property "email_address"
//   "user_name": "name"
// }

Bridge Request:

POST /api/v1/sdk/bridge/capture
Content-Type: application/json
X-App-Id: YOUR_APP_ID

{
  "messageId": "msg_123",
  "formData": {
    "email": "user@example.com",
    "name": "John Doe",
    "newsletter": "true"
  },
  "submitAction": {
    "type": "track_event",
    "eventName": "newsletter_signup",
    "eventProperties": {
      "email_address": "email",
      "user_name": "name"
    }
  },
  "userId": "user_123",
  "external_id": "ext_123"
}

Response:

{
  "success": true,
  "message": "Form data captured",
  "data": {
    "eventId": "event_789",
    "attributesUpdated": []
  }
}

Update Profile

Update customer attributes with form data:

javascript
// Configured in dashboard:
// Submit action type: "update_profile"
// Profile attributes mapping: {
//   "email": "email",
//   "full_name": "name",
//   "newsletter_subscribed": "newsletter"
// }

Bridge Request:

POST /api/v1/sdk/bridge/capture
Content-Type: application/json
X-App-Id: YOUR_APP_ID

{
  "messageId": "msg_123",
  "formData": {
    "email": "user@example.com",
    "name": "John Doe",
    "newsletter": "true"
  },
  "submitAction": {
    "type": "update_profile",
    "profileAttributes": {
      "email": "email",
      "full_name": "name",
      "newsletter_subscribed": "newsletter"
    }
  },
  "userId": "user_123"
}

Response:

{
  "success": true,
  "message": "Form data captured",
  "data": {
    "attributesUpdated": ["email", "full_name", "newsletter_subscribed"]
  }
}

Both Track Event and Update Profile

Perform both actions when the form is submitted:

javascript
// Configured in dashboard:
// Submit action type: "both"
// Event name: "newsletter_signup"
// Event properties: { "email_address": "email" }
// Profile attributes: { "newsletter_subscribed": "newsletter" }

Response:

{
  "success": true,
  "message": "Form data captured",
  "data": {
    "eventId": "event_789",
    "attributesUpdated": ["newsletter_subscribed"]
  }
}

Default Behavior (No Submit Action)

If no submit action is configured, the form data is automatically saved to the customer's profile attributes:

javascript
// Form data is saved as customer attributes
{
  "success": true,
  "message": "Form data captured",
  "data": {
    "attributesUpdated": ["email", "name", "newsletter"]
  }
}

Customer Identification

The Bridge API automatically identifies customers based on the following identifiers (at least one is required):

  • userId - Tappd internal user ID
  • external_id - Your internal user ID
  • email - Customer email address
  • phone - Customer phone number

The SDK automatically includes these identifiers in bridge requests:

javascript
// SDK automatically includes:
{
  "userId": "tappd_user_123",        // From SDK's currentUserId or anonymousId
  "external_id": "your_user_123",     // From identify() call
  "email": "user@example.com",        // From identify() call
  "phone": "+1234567890"              // From identify() call
}

If a customer doesn't exist, one is automatically created with the provided identifiers.

API Endpoints

POST /api/v1/sdk/bridge/action

Handle button actions from in-app messages.

Headers:

Content-Type: application/json
X-App-Id: YOUR_APP_ID

Request Body:

{
  "messageId": "string (required)",
  "actionType": "close" | "track_event" | "update_profile" | "link (required)",
  "actionData": {
    // For track_event:
    "eventName": "string (required)",
    "eventProperties": {} (optional)
    
    // For update_profile:
    "profileAttributes": {} (required)
  },
  "formData": {} (optional),
  "userId": "string (optional)",
  "external_id": "string (optional)",
  "email": "string (optional)",
  "phone": "string (optional)"
}

Response:

{
  "success": true,
  "message": "Bridge action processed",
  "data": {
    // For track_event:
    "eventId": "string"
    
    // For update_profile:
    "updated": true,
    "attributes": ["string"]
    
    // For close:
    "closed": true
  }
}

POST /api/v1/sdk/bridge/capture

Capture form data from in-app messages.

Headers:

Content-Type: application/json
X-App-Id: YOUR_APP_ID

Request Body:

{
  "messageId": "string (required)",
  "formData": {} (required),
  "submitAction": {
    "type": "track_event" | "update_profile" | "both" (optional),
    "eventName": "string (required if type is track_event or both)",
    "eventProperties": {
      "property_name": "form_field_name" (optional)
    },
    "profileAttributes": {
      "attribute_name": "form_field_name" (optional)
    }
  },
  "userId": "string (optional)",
  "external_id": "string (optional)",
  "email": "string (optional)",
  "phone": "string (optional)"
}

Response:

{
  "success": true,
  "message": "Form data captured",
  "data": {
    "eventId": "string (if track_event)",
    "attributesUpdated": ["string"]
  }
}

Usage Examples

Example 1: Button Tracks Event

A promotional banner has a "Learn More" button that tracks a click event:

javascript
// Message configuration (in dashboard):
// Button action: track_event
// Event name: "promo_banner_clicked"
// Event properties: { "campaign": "summer_sale", "position": "top" }

// When user clicks button, SDK automatically:
// 1. Tracks the click event
// 2. Calls /bridge/action with actionType: "track_event"
// 3. Event is created in Tappd with all properties

Example 2: Form Captures Newsletter Signup

A modal form collects email addresses for a newsletter:

javascript
// Message configuration (in dashboard):
// Form fields: email (required), name (optional)
// Submit action: both
// Event name: "newsletter_signup"
// Event properties: { "email": "email" }
// Profile attributes: { "newsletter_subscribed": "true", "email": "email" }

// When user submits form:
// 1. Form data is validated
// 2. Calls /bridge/capture with formData and submitAction
// 3. Event "newsletter_signup" is created
// 4. Customer profile is updated with email and newsletter_subscribed = true

Example 3: Button Updates User Segment

A banner button updates the user's segment when clicked:

javascript
// Message configuration (in dashboard):
// Button action: update_profile
// Profile attributes: { "user_segment": "premium", "upgrade_date": "{{ date }}" }

// When user clicks button:
// 1. Calls /bridge/action with actionType: "update_profile"
// 2. Customer profile is updated with new segment
// 3. Can be used to trigger other journeys based on segment change

Best Practices

  1. Always Identify Users: Ensure users are identified with identify() before they interact with messages to ensure proper customer linking.

  2. Use Descriptive Event Names: Use clear, consistent event names like newsletter_signup, promo_banner_clicked, etc.

  3. Map Form Fields Properly: Use the property/attribute mapping feature to rename form fields to meaningful event properties and profile attributes.

  4. Combine Actions When Needed: Use the "both" submit action type to track events and update profiles simultaneously.

  5. Handle Errors Gracefully: The SDK handles bridge errors internally, but you can check browser console logs for debugging.

  6. Test Your Messages: Always test button actions and form submissions in a development environment before deploying to production.

Troubleshooting

Actions Not Firing

  • Check user identification: Ensure identify() has been called before the message is displayed
  • Verify message configuration: Check that actions are properly configured in the message editor
  • Check browser console: Look for SDK error logs about bridge actions

Form Data Not Captured

  • Validate form fields: Ensure all required fields are filled
  • Check submit action configuration: Verify submit action is configured correctly in the message editor
  • Check network requests: Use browser DevTools to verify /bridge/capture requests are being sent

Customer Not Found

  • Provide identifiers: Ensure at least one identifier (userId, external_id, email, phone) is included in the request
  • Check identification: Verify the user was identified with identify() before the message interaction
  • Review customer creation: Check that customer creation is working properly in your workspace

See Also

Released under the MIT License.