SDK Native - Custom Layouts
Prerequisite: Complete the Native SDK — Customizations guide first.
When the default campaign card does not fit your app, render your own React Native component. You control the card's layout and styles; MCNativeAdView handles campaign fetching, the scrollable list, impression tracking, and default clicks.
How It Works
Pass a function to renderCampaign. The SDK calls it for each campaign and places the returned card inside its own pressable item.
Prop
What it does
renderCampaign(campaign, index)
Returns your custom card for one MCCampaign.
horizontal
Chooses a horizontal carousel (true, the default) or vertical list (false).
renderSkeleton(index)
Optionally returns a loading placeholder matching your card.
onCampaignClick(campaign, index, openDefault)
Optionally replaces click behavior; call openDefault() to continue with the SDK action.
React Native uses components and styles, so there is no XML layout, MCNativeAdRenderer, or getItemLayoutId() to implement. MCNativeAdView loads automatically when mounted. You can also call ref.current?.load() to refresh it later.
The three examples below use one shared helper file for the reward, currency icon, and badges. Create this file once before trying any example:
// CampaignCardParts.tsx
import React from 'react';
import {Image, Text, View} from 'react-native';
import {MCCampaignStatus} from 'mychips-react-sdk';
import type {MCCampaign} from 'mychips-react-sdk';
// Replace with the URL for your app's currency icon.
const CURRENCY_ICON_URL = 'https://your.cdn/currency.png';
export function rewardText(value: number): string {
return Math.round(value).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
export function isInProgress(campaign: MCCampaign): boolean {
const status = campaign.progress?.status;
return !!status &&
status !== MCCampaignStatus.COMPLETED &&
status !== MCCampaignStatus.CLOSED;
}
export function CurrencyIcon({size = 16}: {size?: number}) {
return (
<Image
source={{uri: CURRENCY_ICON_URL}}
style={{width: size, height: size}}
resizeMode="contain"
/>
);
}
export function PromoBadge({ratio}: {ratio: number}) {
if (ratio <= 1) return null;
const multiplier = Number.isInteger(ratio) ? String(ratio) : ratio.toFixed(1);
return (
<Text style={{backgroundColor: '#E65C3A', color: '#FFFFFF',
borderRadius: 12, overflow: 'hidden', paddingHorizontal: 10,
paddingVertical: 4, fontSize: 12, fontWeight: '700'}}>
{multiplier}x Rewards
</Text>
);
}
export function ProgressBadge({campaign}: {campaign: MCCampaign}) {
if (!isInProgress(campaign)) return null;
return (
<Text style={{alignSelf: 'flex-start', backgroundColor: '#E8EDF3',
color: '#424B5A', borderRadius: 5, overflow: 'hidden',
paddingHorizontal: 8, paddingVertical: 3, fontSize: 12}}>
In Progress
</Text>
);
}You may replace CurrencyIcon with a local image such as source={require('./assets/my_currency_icon.png')}. These are app components, so styles and assets belong to your app. The examples use light colors; adjust them for your theme.
Example A: Circular Thumbnails
This example creates a horizontal list with circular thumbnails, promo badges, in-progress indicators, and a currency icon.

Step A.1: Create the card component
Step A.2: Use the custom card
Example B: Vertical Layout (small cards)
This example renders compact vertical rows: a rounded thumbnail on the left, a title and progress badge in the center, and the reward on the right. A promo badge sits above the card's top-right corner.

Step B.1: Create the card component
Step B.2: Use a vertical list
Example C: Vertical Layout (big cards)
This example makes a vertical list of large cards with a wide cover image, title, progress badge, and full-width green reward pill. It uses cover first and falls back to thumbnail only if no cover is available.

Step C.1: Create the card component
Step C.2: Use a vertical list
Key Points for Custom Layouts
Click Handling
MCNativeAdView wraps each custom card in a Pressable. Tapping it opens the campaign detail page by default. To add your own action and then continue with the normal SDK behavior:
If you provide onCampaignClick, call openDefault() when you want the SDK to perform its normal click tracking and navigation. Do not place a second Pressable around the whole custom card unless you intend to handle nested touches.
Image Loading
Use React Native's Image with source={{uri: imageUrl}} for campaign images and remote currency icons, or require(...) for a local icon. Check for an empty image URL and show a placeholder. The example uses resizeMode="cover"; the big card chooses creatives.cover before thumbnail.
List Recycling and Loading
The list can reuse rendered items, so derive every badge, reward, and image from the current campaign. The SDK tracks an impression when a campaign becomes visible; do not call MCOfferwallSDK.trackImpression again for cards in this view.
MCNativeAdView shows its built-in skeleton while loading. If the default shape does not fit your card, pass renderSkeleton={(index) => <YourPlaceholder />} and set skeletonCount as needed. Give the ad view an appropriate height, especially for a vertical list inside another screen.
Next Steps
Need the campaign fields and status constants? See Data Reference →
Want small changes to the default card? See Customizations →
Last updated