Recipe: Publish your app to iOS and Android

Goal

Submit a fresh iOS and Android build to App Store Connect and Google Play Console via the WPMAM publish pipeline.


Prerequisites

  • Enrollment complete and local-app-account_code populated and verified
  • iOS bundle id reserved with Apple; Android package name reserved with Google
  • App icon (1024×1024 PNG), launch screens, and theme assets uploaded
  • APNs .p8 key + Firebase service-account JSON configured
  • Apple Developer Program membership active; Google Play Console developer account active
  • Apple App Store Connect app record created (with the bundle id)
  • Google Play Console app record created (with the package name)

Steps

1. Open the Publish page

Mobile App Manager → Publish Your App opens mam_app_submit::render(). The page first runs verify_account_code() against the WPMAM enrollment server. If verification fails, see Recipe: Customer enrollment and account code.

2. Fill in app identity

Field Option key Notes
iOS app name local-app-ios-app-name Display name on the iOS home screen
iOS bundle id ios_pn_app_bundle_id Frozen — must match App Store Connect
iOS team id ios_pn_team_id 10-character Apple team id
iOS app channel local-app-ios-app-channel TestFlight channel routing
Android package id android_pn_app_bundle_id Frozen — must match Play Console

⚠️ Bundle ids are frozen option keys (predate the mam_* rename convention). Once you’ve submitted to the stores, treat them as immutable; renaming would orphan customer Apple/Google submissions.

3. Fill in permission strings

iOS requires user-facing copy for every privacy-sensitive permission. The publish page collects:

Field Option key Used when
Camera message ios_app_camera_message App requests camera access
GPS message ios_app_gps_message App requests location access
Contacts message ios_app_contacts_message App requests contacts access

These strings ship into Info.plist as NS*UsageDescription. Apple rejects builds with vague or empty copy.

4. Set version and build numbers

Field Option key
iOS version number mam_ios_version_number (e.g., 1.4.2)
Android version number mam_android_version_number
iOS build number mam_ios_build_number (must increment per submission)
Android build number mam_android_build_number (must increment per submission)

⚠️ Build numbers must increment for each new submission. Apple and Google both reject duplicate build numbers within a release train.

5. Configure integrations

Field Option key
iOS Google plist ios_app_google_plist (Firebase config)
Google Places API key ios_app_google_places_api

6. Save settings

Click Save. mam_main_app_publishing::local_app_save_publish_app_settings() writes ~20 options from POST and JSON-responds. The page reloads with the new values.

7. Submit the publish request

Click Submit Publish Request. The handler:

  1. Re-verifies local-app-account_code against WPMAM
  2. Builds a Fastlane settings array from the persisted options
  3. Fires apply_filters('mam_fastlane_settings', $settings) — sibling plugins use this hook to inject build-time config (third-party SDK keys, custom Info.plist entries, gradle properties)
  4. POSTs the payload to the WPMAM publish endpoint
  5. Renders the response as the publish-status panel

The submit is fire-and-forget. WPMAM’s CI runs Fastlane asynchronously; status is polled separately.

8. Monitor build status

Refresh the publish page — the status panel polls WPMAM and shows the latest build state. A successful build appears in App Store Connect (TestFlight) and Google Play Console (Internal Testing) within 30–60 minutes.

If the build fails, the panel shows the Fastlane error. Common causes:

  • Missing or invalid signing certificate (Apple side)
  • Build number not incremented
  • Permission strings missing or rejected
  • Asset corruption (app icon wrong dimensions, launch screens wrong format)

Extending the publish payload

mam_fastlane_settings is the only extension point for the publish payload. Sibling plugins that need to inject build-time config (e.g., a third-party SDK key, a custom URL scheme) should hook here:

add_filter( 'mam_fastlane_settings', function ( array $settings ): array {
    $settings['custom_url_schemes'][] = 'myplugin-callback';
    $settings['ios_extra_plist']['MyPluginAPIKey'] = get_option( 'myplugin_api_key' );
    return $settings;
} );

What WPMAM does with these keys is documented on the WPMAM side; coordinate with the build pipeline team before adding new keys.


Verification

  • The publish-status panel shows “Build queued” or later
  • TestFlight (iOS) shows a new build in 30–60 minutes
  • Google Play Console → Internal Testing shows a new build
  • The mobile app, once installed from the new build, returns the configured app name and shows your branding

Gotchas

  • app-submit.php is 1076 lines of admin-page UI + save flow. Treat it as shared mutable presentation code; small edits can have large knock-on effects.
  • Bundle ids are frozen — they predate the mam_* rename convention. Renaming orphans customer App Store / Play Store submissions.
  • Account-code verification is a guard, not a fix. A mismatch means contact support.
  • Submit POSTs are fire-and-forget by design. The build runs async; status is polled separately. Don’t expect a synchronous success/failure response from the submit.

  • Recipe: Build an app end-to-end
  • Recipe: Customer enrollment and account code
  • Recipe: Configure push notifications
  • Hook: mam_fastlane_settings
  • Frozen public contracts reference

Metadata

Field Value
Article type Recipe (Admin)
Plugin slug mam-main
Applies to plugin version 2.1.11+
Category Building Your App
Audience WordPress admin
Estimated time 30 minutes (excluding store review)
Last verified 2026-05-02
Contents

    Need Support?

    Can’t find the answer you’re looking for? Don’t worry we’re here to help!