Overview
The Tail & Product Format displays recommendations as a separate UI element below your LLM responses. This is the simplest way to integrate AdMesh - just add a component and it handles everything automatically.What you get
- Automatic rendering of recommendations
- Automatic tracking for exposures and clicks
- Transparency labels with
[Ad]added automatically - Session-aware tracking
- Multiple format options, including tail and product cards
At a glance
| Attribute | Tail & Product Format |
|---|---|
| Integration style | Frontend component |
| Best for | Separate recommendation modules |
| Setup time | 5 to 10 minutes |
| Code complexity | Minimal |
| Tracking | Automatic |
| Fallback logic | Handled by the SDK |
Best Fit
Use Tail & Product Format when:- You want recommendations rendered outside the main LLM response
- You want the fastest frontend-only integration path
- You want AdMesh to handle rendering and tracking for you
- You need links woven directly into the assistant response
- You want the backend to control recommendation insertion logic
Implementation Checklist
- Install
admesh-ui-sdk - Wrap your app with
AdMeshProvider - Render
AdMeshRecommendationsfor assistant messages - Pass the original user query and user message ID
- Let the SDK handle exposures, clicks, and labels automatically
Common Use Cases
- chat assistants that show sponsored follow-ups below the answer
- product search experiences that need cards instead of inline links
- recommendation panels in SaaS copilots
- simple prototypes where the team wants the lowest integration effort
Component: AdMeshRecommendations
TheAdMeshRecommendations component is specifically designed for Tail and Product formats. It displays recommendations as a separate UI element (not embedded in your content).
Use this component if:
- ✅ You want a separate recommendations panel
- ✅ You want Tail format (inline tail with links)
- ✅ You want Product format (product cards)
- ✅ You want automatic rendering and tracking
- ❌ You want to embed links directly in LLM responses (use Weave Ad Format instead)
Quick Start - Provider Pattern (Recommended)
The Provider Pattern is the simplest approach - just 3 lines of code!Add AdMeshRecommendations Component
preferred_format. You don’t need to specify a format prop.Format Types
The same component supports two presentation styles. The recommendation payload determines which layout is rendered.Tail Format
Displays a summary with embedded product links. Ideal for conversational interfaces.Product Format
Displays product recommendation cards with key details. Suitable for SaaS or software listings.Tracking Behavior
Tail & Product Format automatically handles:- exposure tracking when recommendations render
- click tracking when a user engages
- transparency labeling with
[Ad] - fallback and error handling in the SDK layer
Format Selection Summary
| Format | Best when | Example experience |
|---|---|---|
| Tail | You want a lighter inline recommendation module | Chat answer with a short sponsored suggestion block |
| Product | You want richer card-based presentation | SaaS comparison or product discovery UI |
Customization
Theme Customization
You can customize the appearance by passing a theme to theAdMeshProvider:
Event Handlers
onRecommendationsShown: Called when recommendations are successfully displayedonError: Called if there’s an error fetching or displaying recommendations
Automatic Tracking
The SDK automatically manages:- Exposure tracking - when recommendations are rendered
- Click tracking - when users engage with recommendations
- Conversion tracking - if configured
- Transparency labels -
[Ad]automatically added
Complete Integration Example
Optional Follow-Up Recommendations
AdMesh can inject sponsored follow-up queries into your existing follow-up suggestions UI. Instead of creating a separate container, you can use your existing follow-up or “Related” section where you already show suggestions to users.Setting Up Follow-Up Recommendations
If your platform already has a follow-up suggestions section (e.g., “Related Questions”, “Suggested Queries”, or similar), AdMesh can add sponsored follow-ups directly into that existing container. Step 1: Identify your existing follow-up container (or create one if you don’t have one):AdMeshRecommendations:
followup_query, the SDK will automatically inject the sponsored follow-up into your container using React portals. It will appear alongside your existing suggestions, seamlessly integrated into your UI.
The SDK automatically:
- Detects follow-up queries from recommendations
- Renders the sponsored follow-up in your existing container
- Handles engagement tracking when users interact with follow-ups
- Calls your
onExecuteQuerycallback when a user clicks the sponsored follow-up
Complete Example
Here’s how Perplexica integrates sponsored follow-ups into their existing “Related” section:Props Reference
| Prop | Type | Required | Description |
|---|---|---|---|
followups_container_id | string | No | DOM element ID where the SDK should render follow-ups. When provided, the SDK uses portal rendering. |
onExecuteQuery | (query: string) => void | Promise<void> | No | Callback invoked when a user clicks a follow-up. Required for follow-up functionality. Typically executes the query to continue the conversation. |
onFollowupDetected | (followupQuery: string, engagementUrl: string, recommendationId: string) => void | No | Optional callback when a sponsored follow-up is detected. Use this for custom integrations if you prefer to handle rendering yourself (advanced use case). |
isContainerReady | boolean | No | Signal indicating if the follow-up container is ready in the DOM. Useful for streaming or delayed rendering scenarios. |
How It Works
-
Detection: When a recommendation includes a
followup_query, the SDK detects it automatically. -
Rendering: When
followups_container_idis provided, the SDK injects the sponsored follow-up into your existing container using React portals. The follow-up appears alongside your existing suggestions, matching your platform’s styling. -
Click Handling: When a user clicks a follow-up:
- The SDK automatically fires engagement tracking (
followup_engagement_url) - Your
onExecuteQuerycallback is invoked with the follow-up query - You execute the query to continue the conversation (e.g., via
sendMessage())
- The SDK automatically fires engagement tracking (
Notes
- Follow-ups are only displayed if the recommendation includes
followup_queryfrom the backend. - The SDK handles all engagement tracking automatically—you only need to provide
onExecuteQueryto continue the conversation. - Use
isContainerReadywhen rendering containers conditionally or after streaming completes.
Best Practices
✅ DO:- Always provide the
queryparameter (required for contextual recommendations) - Pass your own
sessionIdandmessageIdfor accurate tracking - Store the user’s original query with each assistant message (
userQueryanduserMessageIdon assistant messages) - Let the SDK auto-detect format from recommendations (format is determined by
creative_input.preferred_format) - Use the SDK for rendering and tracking (all tracking is automatic)
- Provide
followups_container_idandonExecuteQueryif you want to show sponsored follow-ups in your existing suggestions UI - Customize themes to match your brand via
AdMeshProvidertheme prop - Use separate sessions for each conversation
- Ensure the follow-up container exists in the DOM before providing its ID to
followups_container_id
- Omit the
queryparameter (recommendations won’t be contextual) - Pass assistant message ID instead of user message ID to
messageIdprop - Manually trigger tracking events (the SDK handles all tracking automatically)
- Modify or remove transparency labels (“Ad” labels are required)
- Try to specify format manually (format is auto-detected from recommendations)
- Reuse session IDs across conversations
- Render recommendations outside the SDK-provided components
Troubleshooting
Recommendations Not Showing
Recommendations Not Showing
Check:
queryprop is provided and not empty (required)messageIdprop is provided- API key is valid and set in environment variables
sessionIdprop is provided toAdMeshProvider- Component is wrapped inside
AdMeshProvider
Query Parameter Missing
Query Parameter Missing
Problem: The Then pass it to the component:
query parameter is required for contextual recommendations.Solution: Store the user’s original query and user message ID on assistant messages:API Key Issues
API Key Issues
Check:
- API key is valid and active
- Environment variable is set correctly
- No extra spaces or quotes in the key
Tracking Not Working
Tracking Not Working
Tracking is managed automatically by the SDK. Do not modify tracking logic or URLs manually. The SDK handles all tracking internally.The SDK automatically tracks:
- Exposure events when recommendations are shown
- Click events when users interact with recommendations
- Follow-up engagement events when users click sponsored follow-ups
- All tracking is handled internally - no manual setup needed
Follow-Ups Not Showing
Follow-Ups Not Showing
If you’re using
followups_container_id but follow-ups aren’t appearing:Check:- Container element with the specified ID exists in the DOM
onExecuteQuerycallback is provided (required for follow-up functionality)- Recommendation from backend includes
followup_queryfield - Container is ready before SDK tries to render (use
isContainerReadyif rendering is delayed)
Wrong Format Displayed
Wrong Format Displayed
Format is auto-detected from the recommendation’s
creative_input.preferred_format field. You don’t need to (and shouldn’t) specify format manually.Supported formats:tail: Summary with embedded product links (default)productorproduct_card: Product cardsbridge: Follow-up sponsored recommendations with setup prompts
- Detects format from
creative_input.preferred_format - Renders the appropriate component (Tail, Product Card, or Bridge)
- Handles all format-specific logic internally
format prop on AdMeshRecommendations - format is determined by the backend recommendation.Messages Not Updating
Messages Not Updating
Ensure:
- Each message has a unique
messageId - Assistant messages store the original
userQueryanduserMessageId - Messages array is updated when new messages arrive
- Component is re-rendering with new messages