Inbox & channels·Updated Apr 19, 2026 · 6 min read

Display templates for contact integrations

Customise how external data appears

Display Templates allow you to transform raw JSON data from external APIs into beautiful, structured UI components in the ContactProfileSheet. Instead of showing raw JSON, you can create custom layouts with badges, status indicators, formatted currency, and more.

Table of Contents

Overview

Display Templates use a JSON-based configuration system that defines how external data should be rendered. The template editor provides a visual interface for building these templates, complete with live preview.

Key Features

  • Visual Template Builder: Drag-and-drop interface with live preview
  • Multiple Layout Types: Cards, tables, key-value lists, and text sections
  • Dynamic Data Binding: Use {{variable}} syntax to bind API data
  • Conditional Logic: Show/hide sections based on data values
  • Type Formatting: Automatic formatting for currency, dates, status badges
  • Security: Built-in XSS protection and template validation

Template Structure

Every template has this basic structure:

{
  "type": "card",
  "title": "Customer Information",
  "description": "Account details and subscription status",
  "sections": [
    {
      "type": "key-value-list",
      "title": "Account Details",
      "items": [
        {
          "label": "Plan",
          "value": "{{subscription.plan}}",
          "type": "badge"
        }
      ]
    }
  ]
}

Root Properties

  • type: "card" or "simple" - Layout wrapper type
  • title: Optional title for the template
  • description: Optional description
  • sections: Array of content sections

Section Types

1. Key-Value List

Displays data as labeled key-value pairs:

{
  "type": "key-value-list",
  "title": "Account Information",
  "items": [
    {
      "label": "Customer ID",
      "value": "{{customer_id}}",
      "type": "text"
    },
    {
      "label": "Plan",
      "value": "{{subscription.plan}}",
      "type": "badge"
    },
    {
      "label": "Status",
      "value": "{{subscription.status}}",
      "type": "status"
    }
  ]
}

Renders as:

Customer ID    12345
Plan           [Premium]
Status         [Active]

2. Table

Displays data in a structured table format:

{
  "type": "table",
  "title": "Financial Summary",
  "items": [
    {
      "label": "Lifetime Value",
      "value": "{{lifetime_value}}",
      "type": "currency"
    },
    {
      "label": "Last Purchase",
      "value": "{{last_purchase}}",
      "type": "date"
    }
  ]
}

Renders as:

┌──────────────┬──────────────┐
│ Lifetime Value │ $2,850.00   │
│ Last Purchase  │ Jan 15, 2024 │
└──────────────┴──────────────┘

3. Text

Custom text with variable interpolation:

{
  "type": "text",
  "content": "Customer {{customer_name}} has been a {{subscription.plan}} member since {{join_date}}."
}

4. Separator

Visual separator between sections:

{
  "type": "separator"
}

Field Types

Text

Default display type for plain text values.

{
  "label": "Customer ID",
  "value": "{{customer_id}}",
  "type": "text"
}

Badge

Displays value in a colored badge/pill.

{
  "label": "Plan",
  "value": "{{subscription.plan}}",
  "type": "badge"
}

Status

Colored status indicators with predefined color schemes.

{
  "label": "Status",
  "value": "{{subscription.status}}",
  "type": "status"
}

Status Colors:

  • active → Green
  • pending → Yellow
  • inactive → Gray
  • failed → Red
  • success → Green
  • error → Red

Currency

Formats numbers as currency (USD by default).

{
  "label": "Lifetime Value",
  "value": "{{lifetime_value}}",
  "type": "currency"
}

Example: 2850.00$2,850.00

Date

Formats date strings in readable format.

{
  "label": "Last Purchase",
  "value": "{{last_purchase}}",
  "type": "date"
}

Example: 2024-01-15T10:30:00ZJan 15, 2024

Creates clickable links.

{
  "label": "Profile",
  "value": "{{profile_url}}",
  "type": "link"
}

Variable System

Use {{variable}} syntax to reference data from your API response:

Simple Variables

{{customer_id}} → 12345
{{email}} → [email protected]

Nested Variables

{{subscription.plan}} → Premium
{{billing.address.city}} → New York

Array Access

{{tags.0}} → First tag
{{orders.0.total}} → First order total

Conditional Display

Show/hide sections or items based on data values:

Simple Existence Check

{
  "type": "key-value-list",
  "condition": "{{subscription}}",
  "items": [...]
}

Equality Check

{
  "type": "text",
  "condition": "{{status}} === 'active'",
  "content": "This customer has an active subscription."
}

Inequality Check

{
  "type": "key-value-list",
  "condition": "{{subscription.status}} !== 'cancelled'",
  "items": [...]
}

Repeating Sections

Repeating sections allow you to display array data (like orders, transactions, or tickets) with configurable templates for each item.

Configuration

{
  "type": "repeating-section",
  "title": "Order History", 
  "array_path": "orders",
  "item_template": {
    "sections": [
      {
        "type": "key-value-list",
        "items": [
          {
            "label": "Order ID",
            "value": "{{id}}",
            "type": "text"
          },
          {
            "label": "Status", 
            "value": "{{status}}",
            "type": "status"
          },
          {
            "label": "Amount",
            "value": "{{amount}}",
            "type": "currency"
          },
          {
            "label": "View Order",
            "value": "{{order_url}}",
            "type": "link"
          }
        ]
      }
    ]
  }
}

Properties

  • type: Always "repeating-section"
  • title: Optional section title
  • array_path: Path to the array in your API response (e.g., "orders", "tickets", "transactions")
  • item_template: Template configuration for each array item
  • condition: Optional condition to show/hide the entire section

Array Path Examples

// Simple array path
"array_path": "orders"  // Accesses response.orders

// Nested array path  
"array_path": "customer.orders"  // Accesses response.customer.orders

// Deep nesting
"array_path": "data.customer.order_history"  // Accesses response.data.customer.order_history

Item Template Fields

Within repeating sections, you can use these field types:

  • text - Plain text
  • badge - Colored badge/pill
  • status - Status indicator with predefined colors
  • currency - Formatted currency
  • date - Formatted date
  • link - Clickable link (opens in new tab)

Note: Buttons are not supported within repeating sections for security reasons.

Example API Response

{
  "success": true,
  "orders": [
    {
      "id": 12345,
      "status": "completed",
      "amount": "$450.00",
      "due_date": "2024-02-15",
      "payment_status": "paid",
      "order_url": "https://orders.example.com/12345"
    },
    {
      "id": 12346, 
      "status": "in_progress",
      "amount": "$750.00",
      "due_date": "2024-03-20",
      "payment_status": "pending",
      "order_url": "https://orders.example.com/12346"
    }
  ]
}

Rendered Output

┌─ Order History ──────────────────────┐
│                                      │
│ ┌────────────────────────────────────┐ │
│ │ Order ID      12345                │ │
│ │ Status        [Completed]          │ │  
│ │ Amount        $450.00              │ │
│ │ View Order    [Link] ↗             │ │
│ │ ────────────────────────────────── │ │
│ │ Item 1 of 2                        │ │
│ └────────────────────────────────────┘ │
│                                      │
│ ┌────────────────────────────────────┐ │
│ │ Order ID      12346                │ │
│ │ Status        [In Progress]        │ │
│ │ Amount        $750.00              │ │
│ │ View Order    [Link] ↗             │ │
│ │ ────────────────────────────────── │ │
│ │ Item 2 of 2                        │ │
│ └────────────────────────────────────┘ │
└──────────────────────────────────────┘

Empty State

When the array is empty or doesn't exist:

┌─ Order History ──────────────────────┐
│                                      │
│  No orders found                     │
│                                      │
└──────────────────────────────────────┘

Template Examples

Example 1: Customer Overview

API Response:

{
  "customer_id": 12345,
  "email": "[email protected]",
  "subscription": {
    "plan": "Premium",
    "status": "active",
    "renewal_date": "2024-06-15"
  },
  "support_tier": "Priority",
  "lifetime_value": 2850.00
}

Template:

{
  "type": "card",
  "title": "Customer Overview",
  "description": "Key account information",
  "sections": [
    {
      "type": "key-value-list",
      "title": "Account Details",
      "items": [
        {
          "label": "Customer ID",
          "value": "{{customer_id}}",
          "type": "text"
        },
        {
          "label": "Support Tier",
          "value": "{{support_tier}}",
          "type": "badge"
        },
        {
          "label": "Status",
          "value": "{{subscription.status}}",
          "type": "status"
        }
      ]
    },
    {
      "type": "separator"
    },
    {
      "type": "table",
      "title": "Financial Information",
      "items": [
        {
          "label": "Lifetime Value",
          "value": "{{lifetime_value}}",
          "type": "currency"
        },
        {
          "label": "Plan",
          "value": "{{subscription.plan}}",
          "type": "badge"
        }
      ]
    }
  ]
}

Example 2: Support Ticket Summary

API Response:

{
  "tickets": {
    "total": 15,
    "open": 2,
    "avg_resolution_time": 4.5
  },
  "last_contact": "2024-01-10T14:30:00Z",
  "satisfaction_score": 4.8
}

Template:

{
  "type": "simple",
  "sections": [
    {
      "type": "text",
      "content": "Customer has {{tickets.total}} total tickets with {{tickets.open}} currently open."
    },
    {
      "type": "key-value-list",
      "items": [
        {
          "label": "Last Contact",
          "value": "{{last_contact}}",
          "type": "date"
        },
        {
          "label": "Satisfaction Score",
          "value": "{{satisfaction_score}}/5.0",
          "type": "text"
        },
        {
          "label": "Avg Resolution",
          "value": "{{tickets.avg_resolution_time}} hours",
          "type": "text"
        }
      ]
    }
  ]
}

Example 3: E-commerce Order History

API Response:

{
  "orders": {
    "total_count": 23,
    "total_spent": 5280.50
  },
  "last_order": {
    "date": "2024-01-08T12:00:00Z",
    "total": 159.99,
    "status": "delivered"
  },
  "loyalty_tier": "Gold",
  "is_vip": true
}

Template:

{
  "type": "card",
  "title": "Order History",
  "sections": [
    {
      "type": "key-value-list",
      "condition": "{{is_vip}}",
      "title": "VIP Customer",
      "items": [
        {
          "label": "Loyalty Tier",
          "value": "{{loyalty_tier}}",
          "type": "badge"
        }
      ]
    },
    {
      "type": "table",
      "title": "Order Summary",
      "items": [
        {
          "label": "Total Orders",
          "value": "{{orders.total_count}}",
          "type": "text"
        },
        {
          "label": "Total Spent",
          "value": "{{orders.total_spent}}",
          "type": "currency"
        },
        {
          "label": "Last Order",
          "value": "{{last_order.date}}",
          "type": "date"
        },
        {
          "label": "Last Order Status",
          "value": "{{last_order.status}}",
          "type": "status"
        }
      ]
    }
  ]
}

Best Practices

1. Template Design

  • Keep it Simple: Start with basic key-value lists before adding complexity
  • Use Appropriate Types: Choose the right field type for better visual hierarchy
  • Group Related Data: Use sections to organize related information
  • Provide Context: Add section titles and descriptions for clarity

2. Variable Usage

  • Test Variables: Use the preview pane to ensure variables resolve correctly
  • Handle Missing Data: Variables that don't exist will show as empty
  • Use Descriptive Labels: Make labels clear and user-friendly
  • Consider Data Types: Match field types to your data (dates, currency, etc.)

3. Performance

  • Limit Complexity: Very complex templates may impact rendering performance
  • Use Conditions Wisely: Don't overuse conditional sections
  • Keep Templates Focused: One template per specific data type/purpose

4. User Experience

  • Test with Real Data: Always test templates with actual API responses
  • Consider Edge Cases: What happens when data is missing or unexpected?
  • Maintain Consistency: Use similar layouts across different integrations
  • Get User Feedback: Ask support agents what information they find most useful

Security

Built-in Protection

  • XSS Prevention: Script tags and JavaScript URLs are blocked
  • Template Validation: Structure is validated on save
  • Safe Rendering: Variables are escaped to prevent injection

Security Guidelines

  • Validate External Data: Ensure your APIs return safe, expected data
  • Limit Template Complexity: Complex templates are harder to secure
  • Regular Reviews: Periodically review templates for potential issues
  • User Permissions: Only allow trusted users to create/edit templates

Troubleshooting

Common Issues

Variables not showing data:

  • Check the variable path matches your API response structure
  • Ensure the API is returning the expected data structure
  • Use the preview pane to debug variable resolution

Template not displaying:

  • Verify the template structure is valid
  • Check that display_enabled is true for the integration
  • Ensure the integration is active and returning successful responses

Formatting issues:

  • Verify field types match your data (don't use currency type for text)
  • Check date format compatibility
  • Test with different data values

Performance problems:

  • Simplify complex templates
  • Reduce the number of conditional sections
  • Consider breaking large templates into smaller ones

Getting Help

  1. Use the Template Editor: The live preview helps identify issues immediately
  2. Check Browser Console: Look for JavaScript errors that might indicate problems
  3. Test Integration: Use the test feature in Settings to verify API responses
  4. Review Logs: Check Laravel logs for template validation errors

This completes the Display Templates documentation. Templates provide a powerful way to transform raw API data into beautiful, actionable insights for your support team!

Was this article helpful?
Your feedback helps us improve our docs.