# AdTogether — LLM Integration Reference **Version:** 0.4.5 **"Show an ad, get an ad shown"** *The reciprocal ad exchange to increase conversions and grow your app's audience.* > This directory contains markdown format documentation specifically optimized for LLMs and AI Coding Assistants (like Cursor, GitHub Copilot, or ChatGPT) to quickly ingest context and write integration code for their human users. --- ## IMPORTANT: SDK Selection Guide AdTogether provides **5 separate SDKs**. Each SDK has its **own package name, import path, component names, and API surface**. Do NOT mix APIs between SDKs — they are completely independent codebases. To prevent context bleeding and hallucination, **please read the specific instruction file** for the platform you are building for: | # | SDK Name | Package / Import | Instructions File | Targets | |---|----------|-----------------|-------------|---------| | 1 | **Web SDK** | `@adtogether/web-sdk` | Read `llms-web.txt` | Websites, React, Next.js, Vue, plain HTML | | 2 | **React Native SDK** | `@adtogether/react-native-sdk` | Read `llms-react-native.txt` | React Native (iOS + Android), Expo | | 3 | **Flutter SDK** | `adtogether_sdk` | Read `llms-flutter.txt` | Android + iOS + Web (single Dart package) | | 4 | **Native iOS SDK** | `AdTogether` (Swift) | Read `llms-ios.txt` | SwiftUI, UIKit | | 5 | **Native Android SDK** | `com.adtogether:sdk` | Read `llms-android.txt` | Jetpack Compose | | 6 | **REST API** | Direct API calls | Read `llms-rest.txt` | Custom backend integrations | ### Decision Tree - Building a **website** or **React/Next.js/Vue** app? → **Read `llms-web.txt`** - Building a **React Native** mobile app? → **Read `llms-react-native.txt`** - Building a **Flutter** app (any platform)? → **Read `llms-flutter.txt`** - Building a **pure Swift** iOS app (no Flutter/RN)? → **Read `llms-ios.txt`** - Building a **pure Kotlin** Android app (no Flutter/RN)? → **Read `llms-android.txt`** > **Flutter developers do NOT need SDK #4 or #5.** The Flutter SDK handles native code internally via Platform Channels. --- ## Quick Reference: Key Differences Between SDKs | Feature | Web SDK | React Native SDK | Flutter SDK | iOS SDK | Android SDK | |---------|---------|-----------------|-------------|---------|-------------| | **Init call** | `AdTogether.initialize({ appId })` | `AdTogether.initialize({ appId })` | `await AdTogether.initialize(appId: ...)` | `AdTogether.initialize(appId: ...)` | `AdTogether.initialize(context, appId)` | | **bundleId** | Auto: `hostname` | Auto: expo-app / device-info / manual | Auto: `package_info_plus` | Auto: `Bundle.main` | Auto: `context.packageName` | | **Banner component** | `` | `` | `AdTogetherBanner()` widget | `AdTogetherView()` | `AdTogetherView()` composable | | **Banner close button** | `showCloseButton` + `onAdClosed` | `showCloseButton` + `onAdClosed` | `showCloseButton` + `onAdClosed` | `showCloseButton` + `onAdClosed` | `showCloseButton` + `onAdClosed` | | **Interstitial pattern** | `` | `` | `AdTogetherInterstitial.show(context: ..., adUnitId: ...)` | `.fullScreenCover { AdTogetherInterstitialView(...) }` | `if (show) { AdTogetherInterstitial(..., onDismiss = ...) }` | | **Ad unit ID param name** | `adUnitId` | `adUnitId` | `adUnitId` | `adUnitId` | `adUnitId` | | **Import** | `@adtogether/web-sdk` + `/react` | `@adtogether/react-native-sdk` | `package:adtogether_sdk/adtogether_sdk.dart` | `import AdTogether` | `import com.adtogether.sdk.*` | ### Tracking Payload (all SDKs send these on impression/click) | Field | Web | React Native | Flutter | iOS | Android | |-------|-----|-------------|---------|-----|---------| | `adId` + `token` | ✅ | ✅ | ✅ | ✅ | ✅ | | `appId` + `bundleId` | ✅ | ✅ | ✅ | ✅ | ✅ | | `platform` | `"web"` | `Platform.OS` | auto | `#if os()` | `"android"` | | `environment` | `NODE_ENV` | `__DEV__` | auto | `#if DEBUG` | debuggable flag | | `appName` | — | — | ✅ | ✅ | ✅ | | `appVersion` | — | — | ✅ | ✅ | ✅ | --- ## Technical Notes for AI Agents - A valid `AD_UNIT_ID` looks like `unit_x8f9...` or a descriptive string like `home_bottom_banner` - A valid `APP_ID` looks like `at_k3m7...` - All SDKs communicate with the same REST API endpoints (`/api/ads/serve`, `/api/ads/impression`, `/api/ads/click`). - **Strict Type Enforcement:** The `/serve` API now requires an `adType` parameter (`banner` or `interstitial`). The SDK components (`AdTogetherBanner`, `AdTogetherInterstitial`) handle this automatically under the hood. Custom REST integrations must pass this explicitly. - **Initialization must happen BEFORE any ad rendering call** — place it in app startup logic. - The Web SDK and React Native SDK have nearly identical TypeScript APIs but are **completely separate packages** with different import paths. Never cross-import. - The Flutter SDK's interstitial uses an **imperative** `.show()` method. The Web/React Native SDKs use a **declarative** `` pattern. Do not confuse these. - **All SDKs now support `showCloseButton` and `onAdClosed` on banner ads.** This is a recent addition — older versions may not have it. - **All SDKs auto-detect `bundleId`** except React Native, which requires `expo-application` or `react-native-device-info` to be installed, or manual `bundleId` in init options. --- ## Technical Notes for AI Agents (Core Platform) ### Hub/Dashboard Development (Next.js 16 + Firebase) The AdTogether hub incorporates several "working hacks" to overcome limitations of the Next.js/Firebase Hosting environment: 1. **Firebase Admin Bypass:** Avoid standard imports/bundling for `firebase-admin`. Instead, use `const admin = eval("require('firebase-admin')")`. This prevents Next.js from renaming or incorrectly mapping the module during the `standalone` build process, which otherwise causes "Module not found" errors in production Cloud Functions. 2. **Server Action Serialization:** While Next.js 16 supports Server Actions, they can be unreliable in the production Cloud Functions runtime (serialization issues). **Skill:** Prefer standard API routes (`/api/...`) and client-side `fetch()` for complex backend operations like scraping or AI generation. 3. **Lightweight Scraping:** Avoid heavy, ESM-only dependencies like `cheerio` or `puppeteer` in the backend if possible. They are prone to runtime crashes in Node.js 20 Cloud Functions due to module type conflicts. **Skill:** Use zero-dependency Regex-based extraction for HTML text and images. 4. **Auto-write Orchestration:** - The client calls `/api/generate` to get title/description/image context. - Images are returned as `imageBase64` to bypass CORS issues during preview. - **Client Trick:** The client converts base64 to a `File` object for consistency with the manual upload path: `const blob = await (await fetch('data:image/jpeg;base64,...')).blob();` 5. **Ad Screening:** Campaigns are screened via `/api/screen` (DeepSeek) during submission to ensure compliance with `AD_CONTENT_POLICY.md`. --- ## Live Code Reference for Agents - **SDK Setup Example:** Check `src/components/ExampleAdsButton.tsx` for correct initialization and component usage patterns. - **Auto-write Implementation:** Check `src/app/create-ad/page.tsx` (`handleGenerate`) for the client orchestration logic. - **Admin Configuration:** Check `src/lib/firebase-admin.ts` for the `eval("require(...)")` hack.