Skip to main content

Overview

The Citation & 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 (impressions and clicks)
  • ✅ Transparency labels ([Ad] added automatically)
  • ✅ Session-aware tracking
  • ✅ Multiple format options (citation or product cards)
Setup time: 5-10 minutes | Code complexity: Minimal

Component: AdMeshRecommendations

The AdMeshRecommendations component is specifically designed for Citation 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 Citation format (inline citations with links)
  • ✅ You want Product format (product cards)
  • ✅ You want automatic rendering and tracking
Don’t use this component if:
  • ❌ You want to embed links directly in LLM responses (use Weave Ad Format instead)

The Provider Pattern is the simplest approach - just 3 lines of code!
1

Install the SDK

npm install admesh-ui-sdk@latest
2

Wrap with AdMeshProvider

import { AdMeshProvider } from 'admesh-ui-sdk';

<AdMeshProvider apiKey="your-api-key" sessionId={sessionId}>
  <YourChatComponent messages={messages} />
</AdMeshProvider>
3

Add AdMeshRecommendations Component

import { AdMeshRecommendations } from 'admesh-ui-sdk';

// For each assistant message, display recommendations
{messages.map((msg) => (
  <div key={msg.messageId}>
    {msg.content}
    {msg.role === 'assistant' && (
      <AdMeshRecommendations
        messageId={msg.messageId}
        query={msg.query}  // Required: User's original query
        format="citation"  // or "product"
      />
    )}
  </div>
))}
4

Done!

The SDK automatically:
  • Initializes the SDK
  • Fetches recommendations based on the query
  • Shows recommendations in the specified format
  • Tracks exposures and clicks
  • Handles all API communication

Format Types

Citation Format

Displays a summary with embedded product links. Ideal for conversational interfaces.
<AdMeshRecommendations
  messageId={message.messageId}
  query={userQuery}  // Required
  format="citation"
/>
Output:
"Consider [HubSpot](url) for CRM needs or [Asana](url) for project management."

Product Format

Displays product recommendation cards with key details. Suitable for SaaS or software listings.
<AdMeshRecommendations
  messageId={message.messageId}
  query={userQuery}  // Required
  format="product"
/>

Session Management

The AdMeshProvider manages sessions automatically using the sessionId prop you provide. Each message should have a unique messageId and the user’s original query.
<AdMeshProvider
  apiKey="your-api-key"
  sessionId="user-session-123"  // Unique session ID
>
  <YourChatComponent messages={messages} />
  {messages.map((msg) => (
    msg.role === 'assistant' && (
      <AdMeshRecommendations
        key={msg.messageId}
        messageId={msg.messageId}
        query={msg.query}  // Required: User's original query
        format="citation"
      />
    )
  ))}
</AdMeshProvider>
Message structure:
interface Message {
  messageId: string;  // Unique ID for each message
  role: 'user' | 'assistant';
  content: string;
  query?: string;  // User's original query (required for recommendations)
}
If your platform doesn’t have session IDs yet, use the helper methods:
import { AdMeshSDK } from 'admesh-ui-sdk';

// Generate IDs
const sessionId = AdMeshSDK.createSession();
const messageId = AdMeshSDK.createMessageId(sessionId);

// Use in provider
<AdMeshProvider apiKey="your-api-key" sessionId={sessionId}>
  ...
</AdMeshProvider>
Best practice: Always pass your own sessionId and messageId when available. Store the user’s original query with each assistant message to enable contextual recommendations.

Customization

Theme Customization

import { AdMeshSDK, mergeTheme, injectCustomTheme } from 'admesh-ui-sdk';

const theme = mergeTheme({
  mode: 'dark',
  primaryColor: '#3b82f6',
  accentColor: '#ffffff',
  borderRadius: '0.5rem'
});

injectCustomTheme(theme);

const admesh = new AdMeshSDK({
  apiKey: 'your-api-key'
});

Event Handlers

<AdMeshRecommendations
  messageId={message.messageId}
  query={userQuery}  // Required
  format="citation"
  onRecommendationsShown={(messageId) => {
    console.log('Recommendations shown for message:', messageId);
  }}
  onError={(error) => {
    console.error('Error fetching recommendations:', error);
  }}
/>
Available callbacks:
  • onRecommendationsShown: Called when recommendations are successfully displayed
  • onError: Called if there’s an error fetching or displaying recommendations

Automatic Tracking

The SDK automatically manages:
  1. Exposure tracking - when recommendations are rendered
  2. Click tracking - when users engage with recommendations
  3. Conversion tracking - if configured
  4. Transparency labels - [Ad] automatically added
No additional setup is required.

Complete Integration Example

import React, { useState } from 'react';
import { AdMeshProvider, AdMeshRecommendations } from 'admesh-ui-sdk';

interface Message {
  messageId: string;
  role: 'user' | 'assistant';
  content: string;
  query?: string;  // Store user's original query
}

function ChatWithRecommendations() {
  const [messages, setMessages] = useState<Message[]>([]);
  const [inputQuery, setInputQuery] = useState('');
  const sessionId = 'user-session-123';

  const handleSendMessage = async () => {
    if (!inputQuery.trim()) return;

    // Add user message
    const userMessage: Message = {
      messageId: `msg-${Date.now()}`,
      role: 'user',
      content: inputQuery,
      query: inputQuery  // Store the query
    };

    // Simulate assistant response
    const assistantMessage: Message = {
      messageId: `msg-${Date.now() + 1}`,
      role: 'assistant',
      content: 'Here are some recommendations for you...',
      query: inputQuery  // Store the original query for recommendations
    };

    setMessages([...messages, userMessage, assistantMessage]);
    setInputQuery('');
  };

  return (
    <AdMeshProvider
      apiKey={process.env.REACT_APP_ADMESH_API_KEY}
      sessionId={sessionId}
    >
      <div className="chat-container">
        <div className="messages">
          {messages.map((msg) => (
            <div key={msg.messageId} className={`message ${msg.role}`}>
              <div className="message-content">{msg.content}</div>

              {/* Show recommendations for assistant messages */}
              {msg.role === 'assistant' && msg.query && (
                <AdMeshRecommendations
                  messageId={msg.messageId}
                  query={msg.query}  // Required: User's original query
                  format="citation"
                  onRecommendationsShown={(id) => {
                    console.log('Recommendations shown for:', id);
                  }}
                  onError={(error) => {
                    console.error('Recommendation error:', error);
                  }}
                />
              )}
            </div>
          ))}
        </div>

        <div className="chat-input">
          <input
            type="text"
            value={inputQuery}
            onChange={(e) => setInputQuery(e.target.value)}
            onKeyPress={(e) => e.key === 'Enter' && handleSendMessage()}
            placeholder="Ask for product recommendations..."
          />
          <button onClick={handleSendMessage}>Send</button>
        </div>
      </div>
    </AdMeshProvider>
  );
}

export default ChatWithRecommendations;

Optional: Backend Integration

While the admesh-ui-sdk handles all recommendation fetching from the frontend, you can optionally pre-fetch recommendations on your backend for caching or custom logic.

When to Use Backend Integration

  • ✅ You want to cache recommendations server-side
  • ✅ You need to filter or customize recommendations before displaying
  • ✅ You want to reduce frontend API calls
  • ✅ You’re implementing server-side rendering (SSR)

Backend SDK Installation

npm install @admesh/weave-node@latest

Fetching Recommendations on Backend

import { AdMeshClient } from '@admesh/weave-node';

const client = new AdMeshClient({
  apiKey: process.env.ADMESH_API_KEY
});

// In your API endpoint
app.post('/api/recommendations', async (req, res) => {
  const { sessionId, messageId, query } = req.body;

  const result = await client.getRecommendationsForWeave({
    sessionId: sessionId,
    messageId: messageId,
    query: query  // Required
  });

  if (result.found) {
    res.json({
      recommendations: result.recommendations
    });
  } else {
    res.json({ recommendations: [] });
  }
});
Note: Backend integration is optional. The admesh-ui-sdk can fetch recommendations directly from the frontend without any backend code.

Best Practices

DO:
  • Always provide the query parameter (required for contextual recommendations)
  • Pass your own sessionId and messageId for accurate tracking
  • Store the user’s original query with each assistant message
  • Use the SDK for rendering and tracking
  • Customize themes to match your brand
  • Use separate sessions for each conversation
DON’T:
  • Omit the query parameter (recommendations won’t be contextual)
  • Manually trigger tracking events
  • Modify or remove transparency labels
  • Render recommendations outside the container
  • Reuse session IDs across conversations

Troubleshooting

Check:
  • query prop is provided and not empty (required)
  • messageId prop is provided
  • API key is valid and set in environment variables
  • sessionId prop is provided to AdMeshProvider
  • Component is wrapped inside AdMeshProvider
Common issue:
// ❌ WRONG - Missing query
<AdMeshRecommendations
  messageId={msg.messageId}
  format="citation"
/>

// ✅ CORRECT - Query provided
<AdMeshRecommendations
  messageId={msg.messageId}
  query={msg.query}  // Required
  format="citation"
/>
Problem: The query parameter is required for contextual recommendations.Solution: Store the user’s original query with each message:
const assistantMessage = {
  messageId: generateId(),
  role: 'assistant',
  content: 'Response...',
  query: userQuery  // Store original query
};
Then pass it to the component:
<AdMeshRecommendations
  messageId={msg.messageId}
  query={msg.query}  // Required
  format="citation"
/>
Check:
  • API key is valid and active
  • Environment variable is set correctly
  • No extra spaces or quotes in the key
Example:
<AdMeshProvider
  apiKey={process.env.REACT_APP_ADMESH_API_KEY}
  sessionId={sessionId}
>
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
  • All tracking is handled internally - no manual setup needed
Ensure:
  • Each message has a unique messageId
  • Each message stores the original query
  • Messages array is updated when new messages arrive
  • Component is re-rendering with new messages
Example message structure:
interface Message {
  messageId: string;
  role: 'user' | 'assistant';
  content: string;
  query?: string;  // Required for recommendations
}

Next Steps