Meta Ads - Complete App Promotion support (iOS 14+ / SKAdNetwork)
Ask
Make goal: "app_promotion" fully launchable for iOS. Today the goal maps to Meta's App promotion objective with APP_INSTALLS optimization, and promotedObject: { applicationId, objectStoreUrl } is accepted on the ad set — that covers Android completely — but there is no field anywhere in the create surface for the three things Meta requires on iOS 14+ campaigns. Any iOS app campaign created through Zernio today is silently clamped by Meta to "iOS 13.7 or earlier" (effectively zero deliverable audience).
Scope: campaign/ad-set/ad creation for app installs and app-event optimization, app discovery reads, SKAN-aware insights.
Why
App advertisers are iOS-first. Without these fields the goal exists but can't deliver on the platform that carries most app-install spend.
The failure mode is the worst kind. Creation succeeds, delivery eligibility silently collapses, and the missing flag is immutable on Meta's side — the campaign must be deleted and recreated. Nothing errors; the ad set just shows "Apple App Store (iOS 13.7 or earlier)" in Ads Manager.
The docs are silent either way. The Meta Ads "what you can't do" page doesn't mention app ads or SKAdNetwork, so integrators discover the gap in production.
Meta API level — the gaps, in priority order
Campaign-level
is_skadnetwork_attribution: trueon campaign create (POST /v1/ads/createandPOST /v1/ads/campaigns). Required for any campaign targeting iOS 14+; immutable after creation — it cannot be patched later, so exposing it on an update path (platformSpecificData) does not help. Without it Meta silently clampsuser_ostoiOS_ver_14.0_to_14.4/ pre-14 devices.Campaign-level
promoted_object(application_id+object_store_url). Meta requires the promoted object on the campaign for SKAdNetwork/AEM campaign creation, not only on the ad set.Ad-set
campaign_attributionenum (AEM|SKADNETWORK). Required on every iOS 14+ ad set; must be uniform across all ad sets in the campaign.user_osiOS 14+ targeting (user_os: ["iOS_ver_14.0_and_above"],user_device,device_platforms). Likely already transportable viarawTargeting, but needs (a) confirmation that validation doesn't strip it and (b) documentation — without item 1 it is silently clamped rather than rejected.Store-URL integrity on the creative. Meta rejects the ad with "Object store URL does not match promoted object" unless the creative's
link_data.link(and CTA value link) is character-for-character identical to the ad set'spromoted_object.object_store_url. Zernio must not normalize this URL or append tracking parameters to it. Related existing bug:tracking.urlTagsis dropped on create (seedocs/zernio/BUG-tracking-urltags-dropped.md), which forces integrators to bake tracking templates intolinkUrl— for app ads that workaround is fatal, since the click URL must stay byte-identical to the store URL.url_tagsmust ride on the creative object. Also confirmINSTALL_MOBILE_APP/USE_APPare acceptedcallToActionvalues.SKAN validation rules encoded (or at least not blocked):
billing_eventandoptimization_goalcannot both beAPP_INSTALLS(the fixedIMPRESSIONSbilling is fine),buying_typemust beauction,TARGET_COSTunavailable, deferred deep links unavailable, mobile-app custom audiences unavailable for inclusion targeting.App-event optimization pass-through:
promotedObject.customEventTypealongsideapplicationId+objectStoreUrl(AEO), and theVALUEoptimization goal for app purchase-value bidding.
Reads / product asks
App discovery: expose
GET act_{id}/advertisable_applications(app id, name, supported platforms, store URLs from app settings). There is currently no way to list Meta apps at all, so integrators must hand-enterapplicationId— and the App Dashboard ID vs App Store ID confusion is the most common app-ads integration error. This edge also pre-validates that the ad account has permission to promote the app.Campaign-limit read: passthrough for
GET act_{id}/ios_fourteen_campaign_limits(available SKAN campaign/ad-set slots for the app). Meta caps concurrent iOS 14+ campaigns per app; without this read, creates fail unpredictably against the cap.Insights: iOS 14+ campaigns cannot be aggregated with non-iOS campaigns for conversion metrics (Meta returns nothing on mixed queries) and require the default/unified attribution setting. The async report endpoint should support and document this, and ideally expose SKAN fields (
skan_conversions, postback counts).validateOnlycoverage for all of the above so the whole iOS tree can be dry-run before spend.Docs: an "App promotion" page stating the iOS requirements and the current Android/iOS support split explicitly.
References
Aggregated Event Measurement & SKAdNetwork limitations (campaign flag,
campaign_attribution, limits): https://developers.facebook.com/docs/app-ads/SKAdNetwork-aem-and-limitations/Ad Set promoted object reference: https://developers.facebook.com/docs/marketing-api/reference/ad-promoted-object/
Advantage+ app campaigns (valid optimization/bid/event combinations): https://developers.facebook.com/docs/app-ads/advantage-app-campaigns/
iOS 14 Marketing API changes (
is_skadnetwork_attribution,ios_fourteen_campaign_limits): https://fb.me/iOS14-Marketing-Ads-InsightsApp promotion campaign considerations (Ads Manager behavior, per-app campaign caps): https://www.facebook.com/business/help/651033805513936
Log in to comment and vote
Comments1
Miquel Palet López
Sep 9
Shipped and live. Everything on your priority list is in, with one honest caveat at the end.
The three iOS 14 requirements.
isSkadnetworkAttributionis accepted on campaign create, on bothPOST /v1/ads/createandPOST /v1/ads/campaigns. Campaign-levelpromotedObjectwithapplicationIdandobjectStoreUrlis accepted too, and it is sent only when SKAdNetwork is actually requested, so a plain Android app-install campaign keeps the payload it has today. The ad set takescampaignAttributionasAEMorSKADNETWORK.Targeting.
userOsanduserDeviceare now first-class fields. You were right to flag this: the targeting schema silently dropped any key it did not know, souser_ospassed throughrawTargetingsurvived only by accident and anything else vanished without an error. They are emitted properly now.Store URL integrity. Validation enforces that the creative's link matches
promoted_object.object_store_urlcharacter for character, and there is a test asserting we never normalize it or append anything to it.The urlTags bug you linked to. Real, and fixed. We were writing
url_tagson the ad while reading it back from the creative, so a create-time value always read back as null. Tags now go on the creative on every Meta create flow, and the ad-level value is kept for compatibility.The reads.
GET /v1/ads/advertisable-applicationsreturns id, name, supported platforms and store URLs, so the App Dashboard ID versus App Store ID confusion goes away.GET /v1/ads/ios-fourteen-campaign-limitsexposes the per-app campaign and campaign-group slots. Both verified against a live ad account today.validateOnlynow also covers the full tree, and while implementing it we found and fixed a bug where validation was starting real media uploads before checking the flag.The caveat. We could not complete a live iOS acceptance test, because no app on our own ad account is configured for mobile promotion, so Meta answers our probes with a Misconfigured App error before it ever evaluates the SKAdNetwork fields. The field plumbing, validation and payload shapes are covered by tests and by dry runs, but the first real iOS 14 campaign through this path will be yours. Tell us what Meta says and we will turn it around quickly if anything is off.