npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-target-kit

v1.3.3

Published

Zero-boilerplate Adobe Target & AJO Decisioning SDK for React Native with dynamic Firebase Remote Config and custom UI renderer support.

Readme

React Native Target Kit (react-native-target-kit)

npm version npm downloads TypeScript License: MIT

An enterprise-grade, high-performance Server-Driven UI (SDUI) and Personalization SDK for React Native, designed for Adobe Target, Adobe Journey Optimizer (AJO) Decisioning, and Adobe Experience Platform (AEP) Edge Network.

Deliver personalized, dynamic UI experiences and execute real-time content experiments across mobile applications without requiring App Store or Google Play releases.


📑 Table of Contents


🏛️ Architectural Overview

react-native-target-kit decouples marketing and product experimentation from client release cycles:

┌─────────────────────────────────────────────────────────────────────────┐
│              Adobe Experience Platform / Adobe Target Cloud             │
│        (Activities, Automated Personalization, A/B Test Campaigns)      │
└────────────────────────────────────┬────────────────────────────────────┘
                                     │ Edge Delivery (JSON Proposition)
                                     ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                     @adobe/react-native-aepoptimize                     │
│                  (Adobe Mobile Core & Edge TurboModule)                 │
└────────────────────────────────────┬────────────────────────────────────┘
                                     │ Proposition Map
                                     ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                   react-native-target-kit Core Engine                   │
│  ┌───────────────────────────┐         ┌─────────────────────────────┐  │
│  │   TargetContentManager    │ ◄─────► │     SelectorRegistry        │  │
│  │ (1-Call Batching, Cache)  │         │  (Remote Config / Mappings) │  │
│  └─────────────┬─────────────┘         └─────────────────────────────┘  │
│                │                                                        │
│                ▼                                                        │
│  ┌───────────────────────────┐         ┌─────────────────────────────┐  │
│  │   Schema Validator (Zod)  │ ◄─────► │      RendererRegistry       │  │
│  │    (Fail-Safe Fallbacks)  │         │ (SDUI & Bespoke Components) │  │
│  └─────────────┬─────────────┘         └──────────────┬──────────────┘  │
└────────────────┼──────────────────────────────────────┼─────────────────┘
                 │                                      │
                 ▼                                      ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                      Native React Native UI Layers                      │
│      <TargetSlot /> ──► Dynamic SDUI / Carousels / Banking Suites       │
│      Automated View Impressions (displayed) & Conversion Clicks (tapped)│
└─────────────────────────────────────────────────────────────────────────┘

✨ Key Capabilities

  • Zero-Boilerplate Declarative Slots: Render personalized experiences with <TargetSlot selectorId="hero_banner" />.
  • Full-Spectrum Server-Driven UI (SDUI): Universal recursive layout engine supporting nested boxes, typography, cards, carousels, modals, and interactive buttons.
  • Dynamic Multi-Button Action Routing: Handle 1, 2, or 3+ CTA buttons with automatic deep links, custom routes, and callback telemetry.
  • 1-Call Request Batching: Consolidate multiple target slots across a screen into a single network call to the Adobe Edge Network via <TargetProvider screen="..." />.
  • Fail-Safe Fallback System: Automatic schema validation prevents UI crashes; seamlessly serves bundled native fallbacks if offline or timed out.
  • Automated Interaction Telemetry: Out-of-the-box impression tracking (item.displayed) and conversion metric logging (item.tapped).
  • Dynamic Scope Re-routing: Change mbox-to-placement mappings at runtime via Firebase Remote Config or REST APIs without app updates.
  • Pluggable Architecture: Easily switch between RealOptimizeAdapter in production and MockOptimizeAdapter for unit tests and Storybook development.

📦 Installation & Setup

1. Install Dependencies

npm install react-native-target-kit
# or
yarn add react-native-target-kit

2. Peer Dependencies

Install the official Adobe Experience Platform Mobile SDK packages:

npm install @adobe/react-native-aepcore @adobe/react-native-aepedge @adobe/react-native-aepedgeidentity @adobe/react-native-aepoptimize

(iOS Pod Installation):

cd ios && pod install && cd ..

(Optional — for Firebase Remote Config integration):

npm install @react-native-firebase/app @react-native-firebase/remote-config

3. Application Initialization

Initialize the Adobe SDK and configure TargetKit in your application's entry point (e.g., App.tsx or index.ts):

import { MobileCore, LogLevel } from '@adobe/react-native-aepcore';
import { Edge } from '@adobe/react-native-aepedge';
import { Identity } from '@adobe/react-native-aepedgeidentity';
import { Optimize } from '@adobe/react-native-aepoptimize';
import { TargetKit, RealOptimizeAdapter } from 'react-native-target-kit';

export async function initializePersonalization(): Promise<void> {
  try {
    MobileCore.setLogLevel(LogLevel.DEBUG);

    // 1. Register Adobe Extensions
    await MobileCore.registerExtensions([
      Edge.extension,
      Identity.extension,
      Optimize.extension,
    ]);

    // 2. Configure Adobe Core with Environment App ID
    await MobileCore.configureWithAppId('YOUR_ADOBE_MOBILE_APP_ID');

    // 3. Connect TargetKit to Adobe Optimize SDK
    TargetKit.setAdapter(new RealOptimizeAdapter());

    // 4. Register Placement-to-Scope Mappings (or use Remote Config)
    TargetKit.hydrate('DashboardScreen', {
      hero_placement: 'mbox_dashboard_hero',
      credit_card_offer: 'mbox_credit_card_promo',
    });

    console.log('✅ Personalization engine initialized successfully');
  } catch (error) {
    console.error('❌ Personalization initialization failed:', error);
  }
}

🎯 Core Integration Patterns

1. Standard Declarative Slot

Drop <TargetSlot /> anywhere in your component tree. The SDK handles loading skeletons, proposition resolution, rendering, and impression logging automatically.

import React from 'react';
import { TargetSlot } from 'react-native-target-kit';
import { FallbackHeroBanner } from './components/FallbackHeroBanner';

export function DashboardHeader() {
  return (
    <TargetSlot
      selectorId="hero_placement"
      fallbackComponent={<FallbackHeroBanner />}
      showShimmer={true}
    />
  );
}

2. Multi-Action & Deep Link Routing

When returning dynamic layouts containing multiple buttons or links, intercept user actions using the onTapped callback:

import React from 'react';
import { TargetSlot } from 'react-native-target-kit';
import { useNavigation } from '@react-navigation/native';

export function PromotionalSlot() {
  const navigation = useNavigation();

  return (
    <TargetSlot
      selectorId="promo_banner"
      onTapped={(action, envelope) => {
        console.log(`Action triggered: ${action} | Offer: ${envelope?.offerId}`);

        switch (action) {
          case 'action://apply_loan':
            navigation.navigate('LoanApplicationScreen');
            break;
          case 'action://dismiss':
            // Custom dismissal logic
            break;
          default:
            // Handled automatically if standard URI (https:// or myapp://)
            break;
        }
      }}
    />
  );
}

3. Headless / Render-Props Mode

For scenarios requiring customized animations, gesture handlers, or bespoke JSX layouts:

import React from 'react';
import { View, Text, TouchableOpacity, ActivityIndicator } from 'react-native';
import { TargetSlot } from 'react-native-target-kit';

export function CustomHeroSlot() {
  return (
    <TargetSlot selectorId="hero_placement">
      {({ envelope, loading, onTapped }) => {
        if (loading) return <ActivityIndicator size="small" color="#2563EB" />;
        if (!envelope) return null;

        const { headline, ctaText } = envelope.payload;

        return (
          <View style={styles.customCard}>
            <Text style={styles.title}>{headline}</Text>
            <TouchableOpacity onPress={() => onTapped?.('action://custom_press')}>
              <Text style={styles.button}>{ctaText}</Text>
            </TouchableOpacity>
          </View>
        );
      }}
    </TargetSlot>
  );
}

4. Screen-Level Selective Replacement

Wrap a native layout with <TargetSlot selectorId="screen_id">. Components with matching id props are dynamically replaced with Target offers; non-matching components render their native default UI:

import React from 'react';
import { TargetSlot } from 'react-native-target-kit';
import { NativeHeroBanner, NativeQuickActions, NativePromoCard } from './components';

export function HomeScreen() {
  return (
    <TargetSlot selectorId="homescreen_placement">
      {/* If Target returns an offer for 'banner_hero', this Banner is replaced */}
      <NativeHeroBanner id="banner_hero" />

      {/* Renders default native view unless targeted by Adobe */}
      <NativeQuickActions id="quick_actions" />
      <NativePromoCard id="promo_card" />
    </TargetSlot>
  );
}

🌲 Server-Driven UI (SDUI) Reference

Content Envelope Specification

Every JSON payload returned by Adobe Target must adhere to the ContentEnvelope contract:

interface ContentEnvelope<T = Record<string, unknown>> {
  /** Contract specification version (currently '1.0') */
  schemaVersion: '1.0';

  /** Target slot identifier (maps to <TargetSlot selectorId="..." />) */
  selectorId: string;

  /** Adobe Target Activity / Offer ID (used for telemetry metrics) */
  offerId: string;

  /** Adobe Decision Scope (mbox) name */
  decisionScope?: string;

  /** UI Renderer key (e.g., 'dynamic_layout', 'banner', 'carousel') */
  componentType: ComponentType;

  /** Component-specific data model */
  payload: T;
}

SDUI Primitives Catalog

When using "componentType": "dynamic_layout", you can assemble UI layouts using recursive primitive nodes:

| Primitive Node | Description | Key JSON Properties | Example Use Case | | :--- | :--- | :--- | :--- | | box | Flexbox layout container with complete style token support | children, style (padding, bg, flex, gap, border) | Container wrappers, columns, rows | | card | Elevated surface container with preset border radius | children, style, elevation, shadowColor | Floating promotional cards | | text | Typography element with weight, size, color, & alignment | text, style (fontSize, color, fontWeight, textAlign) | Headings, subtext, disclaimers | | image | Responsive remote image with aspect ratio control | url, aspectRatio, resizeMode, style | Product imagery, hero artwork | | button | Interactive CTA with deep link / action handling | label, action, variant (primary, secondary, outline) | "Apply Now", "Learn More" | | button_group | Multi-button grid / row (1, 2, or 3+ action buttons) | direction (row/column), buttons: Array<ButtonNode> | Dual CTAs ("Accept" / "Decline") | | carousel | Horizontal scrollable card slider with pagination | items: Array<{ headline, imageUrl, action }>, showDots | Feature sliders, product carousels | | modal | Interactive slide-up bottom sheet or dialog popup | triggerButtonText, presentationStyle, title, children | "View Terms & Conditions" sheet | | badge / tag | Status chip indicator with themed styling | label, style, variant (success, warning, info) | "PRE-APPROVED", "LIMITED TIME" | | accordion | Collapsible disclosure section with toggle state | title, defaultExpanded, children | FAQ sections, fee breakdowns | | countdown_timer| Animated countdown timer linked to target timestamp | targetTimestamp, label, digitStyle, expiredMessage | "Offer expires in 02:45:10" | | rating | 5-star review display with review count metric | rating (0-5), starSize, starColor, totalReviewsText | "4.9 ★ (1,420 Reviews)" | | progress_bar | Horizontal completion track | progress (0.0 - 1.0), trackColor, progressColor | Credit limit usage, profile completion | | divider / spacer| Structural layout spacing or hairline rule | color, thickness, size | Section separation |


Enterprise Banking & Domain Renderers

The SDK includes turnkey enterprise banking components auto-registered on import:

| componentType | Backing Renderer | Key Data Fields | Use Case | | :--- | :--- | :--- | :--- | | banner | BannerRenderer | imageUrl, headline, subheadline, ctaText, deepLink | General marketing banners | | carousel | CarouselRenderer | items: Array<{ headline, imageUrl, deepLink }>, showDots | Product & feature carousels | | text_block | TextBlockRenderer | title, body, actionText, deepLink, backgroundColor | Alerts, advisories, notifications | | cta_deeplink | CtaRenderer | label, deepLink, style | Standalone action triggers | | credit_card_offer | CreditCardOfferRenderer | cardName, creditLimit, cardImageUrl, perks, applyUrl | Pre-approved credit card offers | | deposit_offer | DepositOfferRenderer | interestRate, maturityAmount, tenure, ctaUrl | High-yield FD/Savings booster | | bill_reminder_offer | BillReminderRenderer | billerName, amountDue, dueDate, cashbackText, payUrl | Utility bill reminders | | rewards_summary_offer| RewardsSummaryRenderer | pointsBalance, expiringPoints, expiryDate, partners | Loyalty reward point balances | | wealth_sip_offer | WealthSipRenderer | fundName, monthlyAmount, expectedReturn, taxSaving | Mutual fund & SIP recommendations | | instant_loan_offer | InstantLoanRenderer | loanAmount, interestRate, tenureMonths, monthlyEmi | Pre-approved loan with EMI preview |


🧩 Extensibility: Registering Custom Renderers

Add your own custom React Native components for any custom componentType:

import React from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
import { RendererRegistry, RendererProps } from 'react-native-target-kit';

interface EmiCalculatorPayload {
  maxAmount: number;
  interestRate: number;
}

export function EmiCalculatorRenderer({
  envelope,
  onTapped,
}: RendererProps<EmiCalculatorPayload>) {
  const { maxAmount, interestRate } = envelope.payload;

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Calculate Your Loan EMI</Text>
      <Text style={styles.rate}>{interestRate}% p.a. up to ${maxAmount.toLocaleString()}</Text>
      <TouchableOpacity
        style={styles.button}
        onPress={() => onTapped?.('action://open_calculator')}
      >
        <Text style={styles.buttonText}>Open Calculator</Text>
      </TouchableOpacity>
    </View>
  );
}

// Register globally
RendererRegistry.register('loan_calculator', EmiCalculatorRenderer);

📊 Automated Analytics & Telemetry Lifecycle

The SDK automatically coordinates proposition lifecycle events with the Adobe Optimize SDK:

  1. Impression Tracking (displayed):
    • When a <TargetSlot /> renders an offer, the SDK triggers item.displayed(proposition) automatically.
    • View metrics are immediately attributed to the active Adobe Target activity.
  2. Interaction Tracking (tapped):
    • Tapping any dynamic button, link, or invoking onTapped() automatically triggers item.tapped(proposition).
    • Conversion metrics are recorded before forwarding the action to your application.

⚡ Performance & Network Optimization

  • 1-Call Request Batching: Wrap screens with <TargetProvider screen="ScreenName">. The SDK analyzes all registered slots and executes a single batched updatePropositions call to Adobe Edge.
  • Lazy Module Loading: Component renderers are loaded on-demand during render time, preventing startup overhead.
  • In-Memory Caching: Resolved offers are cached in memory to eliminate layout flicker on subsequent screen visits.

📖 API Reference

<TargetSlot /> Props

| Prop | Type | Default | Description | | :--- | :--- | :---: | :--- | | selectorId | string | Required | Placement identifier (e.g. 'hero_banner') | | onTapped | (action?: string, envelope?: ContentEnvelope) => void | undefined | Callback fired on user interaction | | fallbackComponent | ReactNode | null | Fallback component rendered if offer is unavailable | | loadingComponent | ReactNode | ShimmerSkeleton | Custom placeholder shown during loading | | showShimmer | boolean | true | Enables animated shimmer skeleton | | envelope | ContentEnvelope | undefined | Direct envelope override (useful for mock testing) |

<TargetProvider /> Props

| Prop | Type | Default | Description | | :--- | :--- | :---: | :--- | | screen | string | Required | Screen name for batching (e.g. 'HomeScreen') | | children | ReactNode | Required | Child components containing <TargetSlot /> elements |


📜 License

MIT © react-native-target-kit contributors