Placement Events Listener
Event-Driven System: The Teads React Native SDK uses a comprehensive event system through TeadsAdPlacementHandler to manage placement interactions, height changes, and user engagement.
Overview
The Teads React Native SDK provides an event-driven system for managing placement events through the TeadsAdPlacementHandler interface. This handler allows you to:
- Track placement height changes for dynamic sizing
- Handle user interactions (clicks on ads and organic content)
- Monitor widget events and custom data
- Implement custom navigation and analytics
TeadsAdPlacementHandler Interface
The TeadsAdPlacementHandler interface defines four optional event handler methods:
interface TeadsAdPlacementHandler {
onHeightChange?: (newHeight: number) => void;
onRecClick?: (url: string) => void;
onOrganicClick?: (url: string) => void;
onWidgetEvent?: (eventName: string, data: { [key: string]: any }) => void;
}
All methods are optional - implement only the events you need to handle.
Event Types
onHeightChange
Called when the placement height changes. This is essential for dynamic ad sizing.
Event Payload:
newHeight: number- The new height in pixels
When it fires:
- When an ad loads and its dimensions are determined
- When ad content changes and requires resizing
- For Feed Placements: When recommendations load
- For Media Placements: When video ad dimensions are calculated
Example:
import { TeadsAdPlacementFeed, type TeadsAdPlacementHandler } from 'outbrain-react-native';
const handler: TeadsAdPlacementHandler = {
onHeightChange: (newHeight) => {
console.log(`Placement height changed to ${newHeight}px`);
// The component automatically adjusts its height
// You can use this for analytics or UI updates
analytics.track('ad_height_changed', {
height: newHeight,
timestamp: Date.now(),
});
},
};
<TeadsAdPlacementFeed
widgetId="MB_1"
widgetIndex={0}
articleUrl="https://example.com/article/123"
partnerKey="YOUR_PARTNER_KEY"
handler={handler}
/>
onRecClick
Called when a user clicks on a paid recommendation or ad.
Event Payload:
url: string- The URL of the clicked recommendation/ad
When it fires:
- User taps on a paid recommendation (Feed Placement)
- User taps on a video ad (Media Placement)
Default Behavior:
- Feed Placement: SDK automatically opens the URL
- Media Placement: SDK automatically opens the URL outside the app
Example:
const handler: TeadsAdPlacementHandler = {
onRecClick: (url) => {
console.log('Ad/recommendation clicked:', url);
// Track click for analytics
analytics.track('ad_clicked', {
url: url,
placement: 'feed',
timestamp: Date.now(),
});
// SDK handles opening the URL automatically
// You can add custom logic here if needed
},
};
onOrganicClick
Called when a user clicks on organic (non-paid) content.
Event Payload:
url: string- The URL of the clicked organic content
When it fires:
- User taps on organic content in Feed Placement
- Typically not fired for Media Placement (video ads)
Default Behavior:
- No automatic navigation - you should handle navigation yourself
Example:
import { useNavigation } from '@react-navigation/native';
const ArticleScreen = () => {
const navigation = useNavigation();
const handler: TeadsAdPlacementHandler = {
onOrganicClick: (url) => {
console.log('Organic content clicked:', url);
// Track for analytics
analytics.track('organic_clicked', { url });
// Navigate to organic content using your app's navigation
navigation.navigate('Article', { url });
// Or open in custom in-app browser
// InAppBrowser.open(url);
},
};
return (
<TeadsAdPlacementFeed
widgetId="MB_1"
widgetIndex={0}
articleUrl="https://example.com/article/123"
partnerKey="YOUR_PARTNER_KEY"
handler={handler}
/>
);
};
onWidgetEvent
Called for other widget events not covered by the specific handlers above.
Event Payload:
eventName: string- The name of the eventdata: { [key: string]: any }- Additional event data
When it fires:
- Custom widget events
- Error events
- Other placement-specific events
Example:
const handler: TeadsAdPlacementHandler = {
onWidgetEvent: (eventName, data) => {
console.log('Widget event:', eventName, data);
// Handle specific events
if (eventName === 'error') {
console.error('Placement error:', data);
// Handle error appropriately
} else if (eventName === 'impression') {
analytics.track('ad_impression', data);
} else if (eventName === 'viewability') {
analytics.track('ad_viewable', data);
}
},
};
Complete Handler Example
Here's a complete example implementing all event handlers:
import React from 'react';
import { View } from 'react-native';
import {
TeadsAdPlacementFeed,
type TeadsAdPlacementHandler,
} from 'outbrain-react-native';
import { useNavigation } from '@react-navigation/native';
import analytics from './analytics';
const ArticleScreen = () => {
const navigation = useNavigation();
const handler: TeadsAdPlacementHandler = {
onHeightChange: (newHeight) => {
console.log(`Placement height: ${newHeight}px`);
analytics.track('ad_height_changed', { height: newHeight });
},
onRecClick: (url) => {
console.log('Ad clicked:', url);
analytics.track('ad_clicked', { url });
// SDK handles opening the URL
},
onOrganicClick: (url) => {
console.log('Organic clicked:', url);
analytics.track('organic_clicked', { url });
// Navigate using your app's navigation
navigation.navigate('Article', { url });
},
onWidgetEvent: (eventName, data) => {
console.log('Widget event:', eventName, data);
switch (eventName) {
case 'error':
console.error('Placement error:', data);
analytics.track('ad_error', data);
break;
case 'impression':
analytics.track('ad_impression', data);
break;
default:
analytics.track('widget_event', { eventName, data });
}
},
};
return (
<View>
<TeadsAdPlacementFeed
widgetId="MB_1"
widgetIndex={0}
articleUrl="https://example.com/article/123"
partnerKey="YOUR_PARTNER_KEY"
handler={handler}
/>
</View>
);
};
Handler for Multiple Placements
You can use the same handler for multiple placements or create separate handlers:
// Shared handler
const sharedHandler: TeadsAdPlacementHandler = {
onHeightChange: (newHeight) => {
console.log('Height changed:', newHeight);
},
onRecClick: (url) => {
console.log('Clicked:', url);
},
};
// Or separate handlers
const feedHandler: TeadsAdPlacementHandler = {
onHeightChange: (newHeight) => {
console.log('Feed height:', newHeight);
},
};
const mediaHandler: TeadsAdPlacementHandler = {
onHeightChange: (newHeight) => {
console.log('Media height:', newHeight);
},
};
// Usage
<TeadsAdPlacementFeed handler={feedHandler} {...feedProps} />
<TeadsAdPlacementMedia handler={mediaHandler} {...mediaProps} />
Event Handling Best Practices
1. Always Handle Height Changes
Height changes are critical for proper layout:
const handler: TeadsAdPlacementHandler = {
onHeightChange: (newHeight) => {
// Component automatically adjusts, but you can track it
console.log('Height updated:', newHeight);
},
};
2. Implement Analytics Tracking
Track user interactions for analytics:
const handler: TeadsAdPlacementHandler = {
onRecClick: (url) => {
analytics.track('ad_clicked', {
url,
placement: 'feed',
timestamp: Date.now(),
});
},
onOrganicClick: (url) => {
analytics.track('organic_clicked', {
url,
placement: 'feed',
timestamp: Date.now(),
});
},
};
3. Handle Errors Gracefully
Monitor error events:
const handler: TeadsAdPlacementHandler = {
onWidgetEvent: (eventName, data) => {
if (eventName === 'error') {
console.error('Placement error:', data);
// Show user-friendly error message or fallback
}
},
};
4. Clean Up Handlers
The SDK automatically cleans up event listeners when components unmount. However, if you're using refs or external handlers:
import { useRef, useEffect } from 'react';
const ArticleScreen = () => {
const handlerRef = useRef<TeadsAdPlacementHandler>({
onHeightChange: (newHeight) => {
// Handler implementation
},
});
// Handler is automatically cleaned up
return (
<TeadsAdPlacementFeed
handler={handlerRef.current}
{...props}
/>
);
};
Event Payload Reference
Height Change Event
onHeightChange(newHeight: number)
newHeight: Height in pixels (number)
Click Events
onRecClick(url: string)
onOrganicClick(url: string)
url: The URL of the clicked item (string)
Widget Event
onWidgetEvent(eventName: string, data: { [key: string]: any })
eventName: Name of the event (string)data: Additional event data (object with string keys and any values)
Platform-Specific Notes
iOS
- Events are delivered through native bridge
- Height changes are automatically applied to the component
- Click handling respects iOS navigation patterns
Android
- Events are delivered through native bridge
- Height changes are automatically applied to the component
- Click handling respects Android navigation patterns
Troubleshooting
Events Not Firing
- Verify the handler is passed correctly to the component
- Check that the component is mounted and visible
- Verify placement is loading correctly
- Check console for error messages
Height Changes Not Working
- Ensure the component is in a ScrollView or similar container
- Verify the handler's
onHeightChangeis implemented - Check that the placement is loading successfully
Clicks Not Working
- Verify handler methods are implemented
- Check that URLs are valid
- Ensure the placement is interactive (not blocked by other views)
Next Steps
- Settings & Configuration - Advanced configuration options
- Integration Guide - Complete integration examples
- Troubleshooting Guide - Common issues and solutions
Pro Tip: Always implement at least onHeightChange to ensure your layout adapts correctly to dynamic ad sizes. This is especially important for Feed Placements.