RORK LABJP
TOOLING — Rork's developer repos keep moving: rork-xcode was updated on July 16, rork-device on July 15, and rork-plist on July 13OPUS46 — Claude Opus 4.6 is live in Rork, and Rork Max is built to assemble apps on top of Claude CodeSIM — A cloud iOS simulator runs in the browser, with one click to install on a device and two clicks to publish to the App StoreMAX — Rork Max emits pure Swift rather than React Native, reaching iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and even iMessageNATIVE — That opens up HealthKit, ARKit and LiDAR, NFC, Dynamic Island, Live Activities, 3D through Metal, and on-device inference with Core MLSEED — Rork raised a $15M seed led by Left Lane Capital, with Peak XV and a16z Speedrun joining the roundTOOLING — Rork's developer repos keep moving: rork-xcode was updated on July 16, rork-device on July 15, and rork-plist on July 13OPUS46 — Claude Opus 4.6 is live in Rork, and Rork Max is built to assemble apps on top of Claude CodeSIM — A cloud iOS simulator runs in the browser, with one click to install on a device and two clicks to publish to the App StoreMAX — Rork Max emits pure Swift rather than React Native, reaching iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and even iMessageNATIVE — That opens up HealthKit, ARKit and LiDAR, NFC, Dynamic Island, Live Activities, 3D through Metal, and on-device inference with Core MLSEED — Rork raised a $15M seed led by Left Lane Capital, with Peak XV and a16z Speedrun joining the round
Articles/Dev Tools
Dev Tools/2026-06-03Intermediate

Your Rork iOS App Won't Build After Adding AdMob Mediation — Untangling Linker Errors and No-Fill Ads

Added Unity Ads, Liftoff, or InMobi mediation adapters to your Rork/Expo iOS app and suddenly hit ld linker errors or ads that never fill? Here's how to isolate the cause by symptom and fix each layer.

AdMob70mediation2iOS109build error4troubleshooting65SKAdNetwork3CocoaPods3

I added three mediation adapters in one sitting to nudge my AdMob eCPM a little higher. Across my four iOS apps (Beautiful HD Wallpapers, Ukiyo-e Wallpapers, Relaxing Healing, and Law of Attraction Everyday — my RWD-iOS group), I dropped in the Unity Ads, Liftoff, and InMobi adapters. Builds that had been green for months all failed at once with ld: framework not found. I hadn't touched the AdMob SDK itself.

Mediation is often described as "just add the adapter," but in practice you have to touch both the link step and the Info.plist, or you get a two-stage trap: the build won't compile, or it compiles but the ads never fill. Here's the symptom-by-symptom breakdown I wish I'd had on hand.

Split the symptom into three buckets first

Post-adapter trouble can look the same on the surface while the root cause lives in different layers. Pinning down which symptom you have saves a lot of blind trial and error.

  • Symptom A: the build fails at link timeld: framework not found GoogleMobileAdsMediation..., Undefined symbols for architecture arm64, or a duplicate symbol error
  • Symptom B: it builds, but mediation ads never fill — your AdMob mediation report shows zero requests (or a 100% error rate) for the new network
  • Symptom C: it builds and shows ads, but measurement is off — SKAdNetwork postbacks don't arrive and the network's own dashboard reports almost nothing

A is about link and Pod consistency; B and C are almost always Info.plist and initialization order. Let's knock them down in order.

Symptom A: linker errors usually mean a version mismatch

When you see framework not found or Undefined symbols, nine times out of ten the adapter and the AdMob core SDK (Google-Mobile-Ads-SDK) versions don't line up. Each adapter targets a specific range of AdMob SDK versions, and when that drifts, the adapter expects symbols that the core doesn't expose, and linking fails.

Start by pinning both the core and the adapters in your Podfile. If you specify loosely with ~> and let pod update decide, the adapters tend to jump to a newer release on their own and break the match — so I prefer pinning the numbers.

# Podfile — pin the AdMob core and mediation adapters to matching versions
target 'YourApp' do
  use_frameworks! :linkage => :static
 
  # AdMob core (match the range your adapters support)
  pod 'Google-Mobile-Ads-SDK', '12.4.0'
 
  # Mediation adapters (pick the build that supports core 12.x)
  pod 'GoogleMobileAdsMediationUnity'
  pod 'GoogleMobileAdsMediationVungle'   # Liftoff ships under the Vungle adapter name
  pod 'GoogleMobileAdsMediationInMobi'
end

The :linkage => :static line matters. If you've moved Firebase to SPM and kept only the AdMob stack on CocoaPods — a hybrid setup — dynamic frameworks and static libraries can mix and trigger duplicate symbol. Forcing the ad adapters to link statically makes that conflict mostly disappear.

After editing the Podfile, reinstall cleanly so you don't drag along a half-broken state.

# Drop the old Pods and lockfile before reinstalling
rm -rf Pods Podfile.lock
pod deintegrate
pod install --repo-update
 
# Clear Xcode's build cache too (a stale one re-triggers "framework not found")
rm -rf ~/Library/Developer/Xcode/DerivedData/*

If Undefined symbols still won't clear, suspect that the network's own SDK (e.g. InMobiSDK) — not just the adapter — failed to install. Check the pod install log for the core SDK appearing under Installing .... The adapter is only a bridge; the network's underlying SDK comes in as a separate Pod.

Symptom B: it builds but shows nothing — look at Info.plist

Once linking succeeds, the next common one is "mediation ads never come back." If your AdMob mediation report keeps showing zero requests for just the new network, your Info.plist is probably missing entries under SKAdNetworkItems.

On iOS, unless you list each ad network's SKAdNetwork ID in Info.plist, that network's delivery and measurement won't work. Adding the adapter does not insert these IDs automatically.

<!-- Info.plist — list one SKAdNetwork ID per network you added -->
<key>SKAdNetworkItems</key>
<array>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>cstr6suwn9.skadnetwork</string> <!-- Google AdMob -->
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>4dzt52r2t5.skadnetwork</string> <!-- Unity Ads -->
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>gta9lk7p23.skadnetwork</string> <!-- Vungle / Liftoff -->
  </dict>
</array>

Always pull the exact ID for each network from the official, current list — these IDs change over time. Rather than hand-adding one per network, I start from the consolidated mediation list Google publishes and trim it down to the networks I actually use. If your project is managed by Expo, write them into ios.infoPlist in app.config.js instead of editing Info.plist directly, so they survive prebuild.

// app.config.js — keep SKAdNetworkItems from being wiped by Expo prebuild
export default {
  ios: {
    infoPlist: {
      SKAdNetworkItems: [
        { SKAdNetworkIdentifier: 'cstr6suwn9.skadnetwork' },
        { SKAdNetworkIdentifier: '4dzt52r2t5.skadnetwork' },
        { SKAdNetworkIdentifier: 'gta9lk7p23.skadnetwork' },
      ],
    },
  },
};

Symptom C: init order and ATT can wreck measurement

If everything builds and shows ads but a network's revenue is far below reality, suspect the order of the ATT (App Tracking Transparency) prompt and your ad SDK initialization. If you initialize MobileAds before calling requestTrackingAuthorization, the SDK starts in a not-authorized state, and some networks keep sending lower-accuracy requests.

The order should be: request ATT right after launch, and only initialize the ad SDK once you have the response.

// At launch: wait for the ATT response, then initialize MobileAds
import AppTrackingTransparency
import GoogleMobileAds
 
func initializeAdsAfterATT() {
    ATTrackingManager.requestTrackingAuthorization { _ in
        // Initialize once the response is settled — authorized or not
        DispatchQueue.main.async {
            MobileAds.shared.start(completionHandler: nil)
        }
    }
}

Note that you should not skip initialization just because the user denied tracking — ads still serve when denied. The goal is only to initialize after the ATT response is settled. If you control ads from the React Native side, confirm the native launch sequence still honors this order around AppDelegate.

Prevention: add adapters one at a time

My biggest takeaway this round was that I added all three adapters at once. When the linker error hit, isolating which adapter caused it cost me extra time. After running a group of apps with over 50 million cumulative downloads for twelve years, I keep relearning that for revenue-related changes, "one at a time, confirm the build is green, then move on" is the fastest path overall.

Concretely: add one adapter → confirm a clean build → confirm a test ad fills on a real device → confirm requests appear in the AdMob console — finish that for one network before moving to the next. Add the SKAdNetworkItems entries one network at a time too, so you can narrow the cause if measurement breaks.

One more thing: always register an AdMob test device ID and verify with test ads. Repeatedly clicking live ads is a policy violation and undoes the configuration you just got working.

Reference links

Once it's configured, mediation is a low-maintenance system — but that first integration stacks several layers and is easy to get stuck in. I hope this helps you isolate where yours is stuck.

Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Dev Tools2026-05-08
Why Rork Max Cloud Compile Fails — and How to Fix It
A symptom-based guide to fixing Rork Max Cloud Compile failures. Covers code signing errors, Swift version mismatches, dependency resolution failures, and build timeouts with practical solutions.
Dev Tools2026-05-07
Rork iOS App: Why Your App Tracking Transparency Prompt Never Shows Up — and How to Fix It
Three real causes the ATT (App Tracking Transparency) dialog never appears in Rork-generated iOS apps — Info.plist, call timing, and AdMob init order — with working code and on-device verification steps.
Dev Tools2026-05-03
When 'pod install' Fails on Rork-Exported iOS Projects — A Practical Guide for the Apple Silicon Era
Most pod install failures on Rork-generated iOS projects come from the same handful of root causes — Apple Silicon ffi mismatches, Ruby version conflicts, CocoaPods version drift, Xcode path issues, and Hermes/Folly compile errors. Here is the order I work through them.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →