iOS integration

Before you add the BV Garner SDK to your own app, use the BV Garner test app to confirm that your Firebase project, sender profile, and Apple credentials work together. After the test passes, integrate the SDK into your app so devices can register with Bazaarvoice and display review request notifications.

This article is for your iOS developers. It is part of the setup described in Set up push notifications in Portal.

Before you begin

  1. You need a real iPhone or iPad running iOS 15 or later, with a build from TestFlight or Xcode 16.2 or later, and JDK 17. You cannot use simulators because attestation does not work in them, and older iOS versions don't support push notifications in simulators.
  2. An Apple Developer account.
  3. Get the following from your Account Administrator or Technical Administrator:
    1. The App ID from the sender profile. See Create a sender profile article, step 9.
    2. The bundle ID and Team ID registered on the sender profile. The profile's platform must be iOS or Both. See Create a sender profile article, step 7. 
    3. The GoogleService-Info.plist file from the same Firebase project as the uploaded key. The APNs key must already be uploaded to Firebase.

Verify your setup with the BV Garner test app

The BV Garner test app runs the SDK with your Firebase project and your sender profile. Its tester screen shows the result of each step, so you can fix configuration issues before you write any integration code.

Setup overview

To set up the BV Garner test app for push notifications, complete these steps:

  1. Set up a test identity
  2. Get the code
  3. Configure the app
  4. Run the app
  5. Send a test notification

Step 1: Set up a test identity

Use a separate bundle ID for testing, for example, com.yourcompany.shop.bvpushtest. Using your production bundle ID would conflict with your production app.

Step 2: Get the code

Code
git clone https://github.com/bazaarvoice/garner.git
cd garner/test-app/ios
cp client.xcconfig.example client.xcconfig

Keep the checkout folder named garner. The app builds the SDK from source in the same repository. Your own app takes the same package from Swift Package Manager.

Build the SDK framework once, and again after any SDK source changes. This step uses JDK 17.

Code
cd garner/bv-push-sdk
./gradlew :sdk:assembleBVGarnerKitDebugXCFramework

Step 3: Configure the app

Edit client.xcconfig:

Key Value
BV_APP_NAME The name shown under the app icon (optional). The default is BV Garner.
BV_BUNDLE_ID The bundle ID of your Firebase iOS app and your sender profile. The default is bv.garner.test.app.
BV_TEAM_ID Your Apple Team ID, as registered on the sender profile. The app uses it for App Attest.
BV_APP_ID The App ID from your sender profile.
BV_BASE_URL The production endpoint (the default, https://push.prod.bazaarvoice.com), or the QA endpoint your Bazaarvoice contact gives you. Write it as https:/$()/host, because // starts a comment in xcconfig.
BV_GOOGLE_SERVICE_INFO_PLIST Path to your GoogleService-Info.plist. The default is BVGarner/GoogleService-Info.plist. Without this file, the app gets no FCM token.
BV_APS_ENVIRONMENT development (the default) for Xcode builds. Use production for TestFlight builds.

Git ignores client.xcconfig.

Step 4: Run the app

  1. Open test-app/ios/BVGarner.xcworkspace in Xcode. Open the workspace, not the .xcodeproj.
  2. Select the BVGarner scheme and your iPhone, and set your signing team.
  3. Press ⌘R.
  4. Select Allow when the app asks to send notifications.

If package resolution fails, select File > Packages > Reset Package Caches. Then build the SDK framework again.

The test app has four tabs:

Tabs What it shows
Home Whether the device is ready. A banner (for example, "3 of 5 checks pass") and a checklist: device registered, push token sent, user signed in, notifications allowed, and quiet hours. Each problem has a button that fixes it or takes you to the fix.
Account Sign in with a user ID and a customer email (both required). After you sign in, it shows the user and the session, plus Sign out. It always shows Receive pushes (opt in or opt out) and Quiet hours (Off, Default, or Set hours).
Inbox Every push the SDK reported on this device, newest first, with its title, text, time, and outcome (shown, held, hidden and why, or tapped). Filter by All, Shown, Held, or Hidden.
Details Device ID, FCM token, APNs token, App ID, bundle ID, endpoint, user ID, session, opt-out, quiet hours, and last error, each with Copy. It also has Copy all (JSON), Share, recent SDK events, and the raw inspector text.

Step 5: Send a test notification

  1. Send a test push from the Portal: On Home, select Copy device ID and paste it into the Portal's Send test notification dialog. The push appears on the device and in Inbox. Selecting it opens the review page. A test push appears even when no user is signed in.
  2. Send a real push: On Account, enter a user ID and the customer email the push is addressed to, and then select Sign in. When Home shows a green check for User signed in, pushes for that email reach this device.
  3. Test at night: By default, pushes are held from 20:00 to 08:00 device time. On Account, set Quiet hours to Off, or use Set hours for your own window.

If notifications are blocked, Allow on Home opens the app's notification settings. It shows the permission prompt only the first time.

Caution
You cannot use Simulators because attestation does not work in them, and older iOS versions don't support Push Notifications in Simulators.

When every step on the tester screen passes, continue to add the BV Garner SDK to your own app (iOS).

Add the BV Garner SDK to your own app (iOS)

Setup overview

To add the BV Garner SDK to your iOS app, complete these steps:

  1. Add the Swift packages
  2. Check Firebase and Info.plist
  3. Turn on capabilities
  4. Initialize the SDK and forward tokens and pushes
  5. Keep your own notification handling working
  6. Link the signed-in customer
  7. Ask for notification permission
  8. Respect customer preferences (optional)
  9. Add a way to see the Device ID (internal builds)

What you need

  1. Xcode 16.2 or later.
  2. Firebase set up in the app.
  3. The SDK is a Swift package. It uses HTTPS only and connects to the production endpoint by default, so you don't need to set a URL.

Step 1: Add the Swift packages

In Xcode, select File > Add Package Dependencies and add these packages to your app target:

  • https://github.com/bazaarvoice/garner.git, version 1.1.0 (Up to Next Major Version). Add the BVGarner and BVGarnerFirebase products.
  • https://github.com/firebase/firebase-ios-sdk, version 12.0.0 or later. Add FirebaseCore and FirebaseMessaging. Skip this if your app already uses them.

BVGarnerFirebase doesn't link Firebase itself, so your app keeps control of its Firebase version. You don't need BVGarnerNotificationService or a Notification Service Extension.

The package also downloads BVGarnerKit.xcframework, the shared engine, from the GitHub release and checks its checksum. You don't add it as a product. Your network must allow GitHub release downloads.

Step 2: Check Firebase and Info.plist

  1. Add the GoogleService-Info.plist from your production Firebase project to your app target. Its BUNDLE_ID must equal your app's bundle ID.
  2. In your app's Info.plist, add BVPushAppIdentifier (String) with the value $(DEVELOPMENT_TEAM).$(PRODUCT_BUNDLE_IDENTIFIER). Xcode fills in your Team ID and bundle ID, for example ABCDE12345.com.yourcompany.shop. It must match the sender profile.
  3. Add FirebaseAppDelegateProxyEnabled (Boolean) set to NO. Your app passes tokens and pushes to the SDK itself.

Step 3: Turn on capabilities

On your app target, open Signing & Capabilities, select + Capability, and add:

  • Push Notifications
  • Background Modes, with Remote notifications selected. Bazaarvoice review requests arrive as background pushes, and the SDK shows the notification itself.
  • App Attest, with the environment set to production for every build, including builds you run from Xcode. In the entitlements file, that's com.apple.developer.devicecheck.appattest-environment set to production.

Your app's identifier in Apple Developer (Certificates, Identifiers & Profiles > Identifiers) must also have Push Notifications and App Attest turned on.

Step 4: Initialize the SDK and forward tokens and pushes

Call configure once in your app delegate's didFinishLaunchingWithOptions, with your App ID:

Code
}
  • configure is lightweight on the main thread. Registration, App Attest, and token sync run in the background. There's no separate register call.
  • configure never throws. If the App ID is invalid, the SDK stays inactive and emits an INVALID_APP_ID error event.
  • If you have a UIKit app, add the same calls to your existing AppDelegate.

Step 5: Keep your own notification handling working

If your app already handles notifications or Firebase tokens, add the SDK calls next to your code:

  • Your own notification center delegate — Set it before you call BVPushUserNotificationCenterProxy.install(). The proxy handles only Bazaarvoice notifications and passes everything else to your delegate.
  • Your own background push handling — Keep it in didReceiveRemoteNotification, and also call BVPushBackground.didReceiveRemoteNotification. For other pushes, it completes with .noData and does nothing else.
  • Your own MessagingDelegate — Also call BVPushFirebase.didReceiveRegistrationToken(fcmToken). Otherwise, the SDK never gets a push token, and BVPush.diagnostics() reports tokenSynced=false.
Code
// After the customer signs in. Safe to call again for the same user.
try BVPush.linkIdentity(userId: customer.id, email: customer.email)

// When the customer signs out
BVPush.unlinkIdentity()
  • Use the same email address that you send to Bazaarvoice in your purchase (transaction) data.
  • userId is sent as is. Use your internal customer ID, not an email address or name.
  • You can call linkIdentity before registration finishes. The SDK keeps the user and links them as soon as the device is registered and has a push token.
  • linkIdentity throws only if the user ID is empty or too long, the email isn't valid, or you call it before configure.
  • Without a linked user, the SDK hides review requests on that phone. Call linkIdentity on every sign-in, and on app start if the customer is already signed in.

Step 7: Ask for notification permission

BVPush.requestNotificationAuthorization() shows the system prompt and registers for remote notifications when the customer allows them. If your app asks for permission itself, call BVPush.refreshNotificationPermission() after the customer answers, so the SDK knows the result.

If the customer denies permission or turns off notifications in iOS Settings, the SDK quietly suppresses review requests on that phone and doesn't show an error.

Step 8: Respect customer preferences (optional)

Code
BVPush.optOut()    // Customer turned off review requests in your app's settings
BVPush.optIn()     // Customer turned them back on
try BVPush.setQuietHours(startHour: 22, startMinute: 0, endHour: 7, endMinute: 0)  // Hold pushes from 22:00 to 07:00 device time
BVPush.disableQuietHours()   // Show pushes at any time
BVPush.resetQuietHours()     // Back to the default, 20:00 to 08:00

Quiet hours use the device's local time. A push that arrives during quiet hours is held. The default is 20:00–08:00.

To handle a notification tap yourself instead of letting the SDK open the review page, use BVPush.setNotificationTapHandler, and then call BVPush.openReview(notificationId:) when you're ready.

Step 9: Add a way to see the Device ID (internal builds)

Testers need the Device ID to verify the sender profile. Show it on an internal or debug screen, or log it:

Code
import BVGarner

func logBVPushDetails() {
    // nil until registration finishes
    print("Bazaarvoice Device ID: \(String(describing: BVPush.testDeviceIdentifier))")
    // No secrets, so it's safe for support tickets
    print(String(describing: BVPush.diagnostics()))
}

After the customer signs in, diagnostics() should show registered, tokenSynced, and hasSession as true.

For more SDK detail in the Xcode console, pass BVPush.Options(logLevel: "debug") to configure in internal test builds only. You can also observe BVPush.observeState and BVPush.observeEvents. These events stay on the phone and are never uploaded.

Next step

Verify your sender profile by sending a test notification, create a notification template in Review Channels, test it, and publish it to your site. For detailed instructions, refer to Verify and publish notification template.

Provide feedback button