Skip to main content

Placement Events Listener

info

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 event
  • data: { [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 onHeightChange is 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


tip

Pro Tip: Always implement at least onHeightChange to ensure your layout adapts correctly to dynamic ad sizes. This is especially important for Feed Placements.