Docs
grovs.io Start for free

API reference

Every public type, property and method in the Grovs iOS SDK 3.1.

Requires iOS SDK 3.1.0

All members are static on Grovs, except the extension types. Completions and delegate callbacks run on the main thread.

At a glance

AreaMemberKindWhat it does
SetupconfiguremethodConfigures and authenticates the SDK
delegatepropertyReceives deep links and SDK errors
setSDKmethodTurns collection on or off
setDebugmethodSets the minimum log level
Deep linkshandleSceneDelegate(openURLContexts:)methodForwards scene URL opens
handleSceneDelegate(continue:)methodForwards scene universal links
handleSceneDelegate(options:)methodForwards the cold-start link
handleAppDelegate(continue:restorationHandler:)methodForwards app delegate universal links
handleAppDelegate(open:options:)methodForwards app delegate URL opens
lastReceivedPayloadmethodMost recent deep link payload
allReceivedPayloadsSinceStartupmethodEvery payload since launch
UsersuserIdentifierpropertyYour ID for the current user
userAttributespropertyAttributes of the current user
LinksgenerateLinkmethodCreates a smart link
linkDetailsmethodDetails of a link by path
EventstrackmethodTracks a custom event
trackScreenViewmethodTracks a screen view
setGlobalTagsmethodTags added to every event
setScreenAliasesmethodRenames screens for the dashboard
screenNameProviderpropertyCustom resolver for screen names
RevenuelogInAppPurchasemethodLogs an App Store purchase
logCustomPurchasemethodLogs a purchase outside the App Store
Push notificationspushTokenpropertyAPNs token as a hex string
setPushTokenmethodSets the token from APNs Data
handleNotificationResponsemethodHandles a notification tap
handleNotificationOpenmethodHandles a tap from its payload
isGrovsNotificationmethodChecks if Grovs sent a push
In-app messagesinAppDelegatepropertyReceives in-app message events
pauseInAppMessagesmethodHolds messages back
resumeInAppMessagesmethodLets messages show again
discardInAppMessagesmethodDrops the waiting message
setInAppExcludedScreensmethodScreens where no message shows
setInAppDebugLoggingmethodLogs why campaigns were skipped
TypesGrovsDelegateprotocolDeep link and error callbacks
GrovsErrorenumSDK error categories
GrovsInAppDelegateprotocolIn-app message callbacks
GrovsScreenTrackingprotocolNames a view controller
GrovsScreenNameenumResult of screenNameProvider
LogLevelenumLog verbosity
TransactionTypeenumBuy, cancel or refund
CustomRedirectstypePer-platform link redirects
CustomLinkRedirecttypeOne platform redirect
Closure typescallbackCompletion signatures
ExtensionsGrovsNotificationServiceExtensionclassAdds campaign images to pushes
GrovsNotificationContentenumImage helper for existing extensions
grovsScreenmethodSwiftUI screen view modifier
trackScreenView (modifier)methodAlias of grovsScreen
DeprecateddisplayMessagesViewControllermethodShows nothing
numberOfUnreadMessagesmethodAlways 0

Setup

configure

method
Swift
static func configure(
    APIKey: String,
    useTestEnvironment: Bool,
    baseURL: String? = nil,
    autoTrackScreenViews: Bool = true,
    clipboardDomains: [String]? = nil,
    enabled: Bool = true,
    delegate: GrovsDelegate?,
    completion: GrovsBoolCompletion? = nil
)

Configures and authenticates the SDK. Call once per launch, in application(_:didFinishLaunchingWithOptions:).

NameTypeDescription
APIKeyStringProject API key from the Grovs dashboard.
useTestEnvironmentBooltrue targets the test environment, false production.
baseURLString?Domain of a self-hosted backend, for example "https://sdk.example.com". The SDK appends the API path. Defaults to the Grovs cloud.
autoTrackScreenViewsBoolTrack screen views automatically by hooking viewDidAppear. Defaults to true.
clipboardDomains[String]?Extra link hosts accepted by clipboard-assisted deferred deep linking, for example ["links.example.com"]. Grovs-owned hosts are always accepted.
enabledBoolWhether the SDK may collect and send anything this launch. Defaults to true.
delegateGrovsDelegate?Receives deep link payloads and SDK errors. Held weakly.
completionGrovsBoolCompletion?Called on the main thread with whether authentication succeeded.
  • Calling it again replaces the previous configuration.
  • enabled isn't persisted. Pass your stored consent value every launch. With enabled: false the completion reports false without attempting authentication.
  • An invalid baseURL, or one without a host, refuses configuration: the completion reports false and the SDK stays unconfigured.
  • On a background launch before the device's first unlock since reboot, configuration waits until the device is unlocked or the app becomes active. Consent, userIdentifier, userAttributes, global tags and screen aliases set meanwhile are applied then.

Calls made before configure:

CallsEffect
Deep link handlers, notification taps, pushTokenHeld until configure runs
setDebug, screenNameProvider, in-app methodsApplied immediately
userIdentifier, userAttributes, track, trackScreenViewIgnored, logs an error
setGlobalTags, setScreenAliasesIgnored silently
Methods with a completionCompletion gets nil or false

delegate

property
Swift
static var delegate: GrovsDelegate?

Receives deep link payloads and SDK errors. See GrovsDelegate.

  • Held weakly. Keep a strong reference elsewhere.
  • Setting it before configure has no effect. Pass it to configure or set it afterwards.
  • Read it on the main thread.

setSDK

method
Swift
static func setSDK(enabled: Bool)

Turns collection on or off at runtime, for example when consent changes. See Privacy & Consent.

  • While disabled, the SDK doesn't authenticate, resolve the device, or send events, screen views or purchases.
  • It holds userIdentifier, userAttributes, pushToken and screen alias updates. Events and purchases on disk stay there.
  • Enabling authenticates if needed and sends everything held.

setDebug

method
Swift
static func setDebug(level: LogLevel)

Sets the minimum log level. Default .error.

  • Works before configure.
  • Logs go through os_log. In release builds, message content is private and shows as <private> in Console.app.

Forward each system entry point to Grovs. Links received before configure are held until it runs. See Deep Linking.

handleSceneDelegate (openURLContexts)

method
Swift
static func handleSceneDelegate(openURLContexts URLContexts: Set<UIOpenURLContext>)

Forward from scene(_:openURLContexts:).

handleSceneDelegate (continue)

method
Swift
static func handleSceneDelegate(continue userActivity: NSUserActivity)

Forward from scene(_:continue:).

handleSceneDelegate (options)

method
Swift
static func handleSceneDelegate(options connectionOptions: UIScene.ConnectionOptions)

Forward from scene(_:willConnectTo:options:). Handles a link that cold-started the app.

handleAppDelegate (continue)

method
Swift
static func handleAppDelegate(
    continue userActivity: NSUserActivity,
    restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool

Forward from application(_:continue:restorationHandler:) and return its result.

  • Main thread only. UIKit already calls your app delegate there.

handleAppDelegate (open)

method
Swift
static func handleAppDelegate(
    open url: URL,
    options: [UIApplication.OpenURLOptionsKey: Any] = [:]
) -> Bool

Forward from application(_:open:options:) and return its result.

  • Main thread only.
  • Returns false for a custom scheme other than your project's Grovs URL scheme, such as a sign-in callback, so another handler after Grovs in an || chain still gets it. Grovs still looks it up, without its query and fragment.

lastReceivedPayload

method
Swift
static func lastReceivedPayload(completion: @escaping GrovsPayloadClosure)

Gets the most recent deep link payload, or nil.

allReceivedPayloadsSinceStartup

method
Swift
static func allReceivedPayloadsSinceStartup(completion: @escaping GrovsPayloadsClosure)

Gets every payload received since the app launched, or nil.


Users

userIdentifier

property
Swift
static var userIdentifier: String?

Your identifier for the current user, typically your user_id. Shown in the dashboard and reports.

  • Set it after configure.
  • While the SDK is disabled, changes are held until it's enabled.

userAttributes

property
Swift
static var userAttributes: [String: Any]?

Attributes of the current user, shown in the dashboard.

  • Values must be JSON-representable: strings, numbers, booleans, NSNull, or arrays and dictionaries of those. An assignment with any other value is rejected and logged.
  • Held while the SDK is disabled.

method
Swift
static func generateLink(
    title: String? = nil,
    subtitle: String? = nil,
    imageURL: String? = nil,
    data: [String: Any]? = nil,
    tags: [String]? = nil,
    customRedirects: CustomRedirects? = nil,
    showPreviewiOS: Bool? = nil,
    showPreviewAndroid: Bool? = nil,
    copyToClipboardiOS: Bool? = nil,
    copyToClipboardAndroid: Bool? = nil,
    trackingCampaign: String? = nil,
    trackingSource: String? = nil,
    trackingMedium: String? = nil,
    completion: @escaping GrovsURLClosure
)

Creates a smart link. See Link Creation.

NameTypeDescription
titleString?Link preview title.
subtitleString?Link preview subtitle.
imageURLString?Link preview image URL.
data[String: Any]?Custom payload delivered on deep link open.
tags[String]?Tags for filtering and analytics.
customRedirectsCustomRedirects?Per-platform redirect overrides.
showPreviewiOSBool?Show the preview page on iOS. nil uses the project default.
showPreviewAndroidBool?Show the preview page on Android. nil uses the project default.
copyToClipboardiOSBool?Copy the link on the iOS preview page, for clipboard-assisted deferred deep linking. nil uses the project default.
copyToClipboardAndroidBool?Same, for the Android preview page.
trackingCampaignString?UTM campaign.
trackingSourceString?UTM source.
trackingMediumString?UTM medium.
completionGrovsURLClosureGets the URL, or nil on failure.

linkDetails

method
Swift
static func linkDetails(path: String, completion: @escaping GrovsLinkClosure)

Gets details for a link generated in the current environment, by path.

Returns through completion: the details, or nil if the request fails.


Events

See Events & Screen Tracking.

track

methodSince 3.0
Swift
static func track(_ name: String, properties: [String: Any]? = nil, tags: [String]? = nil)

Tracks a custom event.

trackScreenView

methodSince 3.0
Swift
static func trackScreenView(_ screenName: String, properties: [String: Any]? = nil)

Tracks a screen view.

  • screen_name is added to the properties.
  • A repeat of the same name within one second is dropped.

setGlobalTags

methodSince 3.0
Swift
static func setGlobalTags(_ tags: [String]?)

Sets tags attached to every later event. Pass nil to clear them.

setScreenAliases

methodSince 3.0
Swift
static func setScreenAliases(_ aliases: [String: String])

Maps view controller class names to dashboard names, for example ["CheckoutViewController": "Checkout Page"].

screenNameProvider

propertySince 3.0
Swift
static var screenNameProvider: ((UIViewController) -> GrovsScreenName)?

Optional resolver for automatically tracked screen names. Returns a GrovsScreenName.

  • Consulted before the SDK's own rules.
  • Called on the main thread. Works before configure.
  • See Custom resolver.

Revenue

See Revenue.

logInAppPurchase

methodSince 3.0
Swift
static func logInAppPurchase(transactionID: UInt64, completion: @escaping GrovsBoolCompletion)

Logs an App Store purchase by its StoreKit 2 transaction ID.

  • Only the ID is sent. The backend resolves product, price and currency through the App Store Server API.
  • An ID already logged on this device is skipped.
  • The completion gets true once sent. Once configured and enabled, false means the purchase is kept and retried, so don't log it again.
  • Getting the ID needs StoreKit 2 (iOS 15) in your code.

logCustomPurchase

methodSince 3.0
Swift
static func logCustomPurchase(
    type: TransactionType,
    priceInCents: Int,
    currency: String,
    productID: String,
    startDate: Date? = nil,
    completion: @escaping GrovsBoolCompletion
)

Logs a purchase, cancellation or refund made outside Apple In-App Purchase.

NameTypeDescription
typeTransactionTypebuy, cancel or refund.
priceInCentsIntPrice in minor units.
currencyStringISO 4217 code.
productIDStringYour product identifier.
startDateDate?Defaults to now.
completionGrovsBoolCompletiontrue once sent. Once configured and enabled, false means the purchase is kept and retried, so don't log it again: a second call is a second purchase.

Push notifications

Setup: Push Notifications.

pushToken

property
Swift
static var pushToken: String?

The APNs device token as a hex string, for push campaigns.

setPushToken

methodSince 3.1
Swift
static func setPushToken(deviceToken: Data)

Sets pushToken from the token passed to application(_:didRegisterForRemoteNotificationsWithDeviceToken:).

handleNotificationResponse

methodSince 3.1
Swift
@discardableResult
static func handleNotificationResponse(_ response: UNNotificationResponse) -> Bool

Handles a tapped Grovs push. Call from userNotificationCenter(_:didReceive:withCompletionHandler:).

Returns true when Grovs sent the notification, whatever the action.

  • Reports a campaign open (push_open, once per device) and delivers the push to grovsReceivedPayloadFromDeeplink.
  • The payload is userInfo without aps, merged over the link's payload if there is one. The push's keys win.
  • Dismissals and custom actions aren't opens.
  • Taps before configure are held until it runs.

handleNotificationOpen

methodSince 3.1
Swift
@discardableResult
static func handleNotificationOpen(userInfo: [AnyHashable: Any]) -> Bool

Same as handleNotificationResponse, when you only have the payload. Always treated as a tap.

  • Never call it from application(_:didReceiveRemoteNotification:fetchCompletionHandler:) or userNotificationCenter(_:willPresent:withCompletionHandler:). Every delivery would count as an open.

isGrovsNotification

methodSince 3.1
Swift
static func isGrovsNotification(userInfo: [AnyHashable: Any]) -> Bool

Checks whether Grovs sent the push as part of a campaign, without handling it.

Returns true when grovs_campaign_id is non-empty.

  • Since 3.1, a push with only grovs_notification_id returns false.

In-app messages

See In-app messages. Every method here works before configure and keeps its effect across later configure calls.

inAppDelegate

propertySince 3.1
Swift
static var inAppDelegate: GrovsInAppDelegate?

Receives in-app message events (shown, tapped, dismissed, answered) and can stop a message. See GrovsInAppDelegate.

  • Held weakly. Read it on the main thread.
  • Messages show without it. See React to messages.

pauseInAppMessages

methodSince 3.1
Swift
static func pauseInAppMessages()

Holds in-app messages back, during a checkout or video, say. The newest highest priority one waits.

resumeInAppMessages

methodSince 3.1
Swift
static func resumeInAppMessages()

Lets messages show again, starting with the one that waited, if it still qualifies.

discardInAppMessages

methodSince 3.1
Swift
static func discardInAppMessages(dismissCurrent: Bool = false)

Drops the waiting message and stays paused. With dismissCurrent: true, also closes the message on screen.

setInAppExcludedScreens

methodSince 3.1
Swift
static func setInAppExcludedScreens(_ screens: [String])

Sets screens where no message shows. Messages wait until the user leaves.

  • Use tracked screen names, from trackScreenView or automatic tracking.
  • Case is ignored.

setInAppDebugLogging

methodSince 3.1
Swift
static func setInAppDebugLogging(_ enabled: Bool)

Logs, at info level, each campaign considered for an event and why it was skipped.


Types

GrovsDelegate

protocol
Swift
@objc public protocol GrovsDelegate: AnyObject {
    func grovsReceivedPayloadFromDeeplink(link: String?, payload: [String: Any]?, tracking: [String: Any]?)
    @objc optional func grovsDidEncounterError(_ error: GrovsError, message: String)
}

Receives deep link payloads and SDK errors. Set it with configure or delegate.

NameTypeDescription
linkString?The link that opened the app, or nil if unavailable.
payload[String: Any]?The custom data attached to the link.
tracking[String: Any]?Attribution and campaign metadata for the link.
  • Both methods run on the main thread.
  • Since 3.1 the protocol is @objc, so Objective-C apps can adopt it.
  • grovsDidEncounterError is an @objc optional method, not a Swift default implementation. A signature that doesn't match exactly compiles with only a "nearly matches" warning and is never called.

GrovsError

enum
Swift
@objc public enum GrovsError: Int, CustomStringConvertible {
    case authenticationFailed = 1
    case networkRequestFailed = 2
    case eventDispatchFailed = 3
    case linkGenerationFailed = 4
    case inAppDisplayFailed = 5
}

Failure categories reported through grovsDidEncounterError. See Handling SDK errors.

  • inAppDisplayFailed (new in 3.1): an in-app message couldn't be drawn. It gains no view and retries at its next trigger.
  • An exhaustive switch needs a case for inAppDisplayFailed.
  • description is the snake-case name, for example "authentication_failed".

GrovsInAppDelegate

protocolSince 3.1
Swift
@objc public protocol GrovsInAppDelegate: AnyObject {
    @objc optional func grovsShouldShowInAppMessage(campaignID: String) -> Bool
    @objc optional func grovsDidShowInAppMessage(campaignID: String)
    @objc optional func grovsDidTapInAppMessage(campaignID: String, buttonID: String?, payload: [String: Any]?)
    @objc optional func grovsDidDismissInAppMessage(campaignID: String, reason: String)
    @objc optional func grovsDidAnswerInAppMessage(campaignID: String, value: Any, comment: String?)
}

Receives in-app message events. Every method is optional and runs on the main thread.

MethodCalled when
grovsShouldShowInAppMessageA message is about to show. Return false to stop it. It isn't counted as seen, and nothing else is shown for that event.
grovsDidShowInAppMessageA message is on screen.
grovsDidTapInAppMessageThe user taps. buttonID is nil for a tap on the message itself. payload is set for a key-value action.
grovsDidDismissInAppMessageA message closes. See the reasons below.
grovsDidAnswerInAppMessageAn answered message has closed, in place of the dismissal. value is an Int for stars, the option's ID for a choice. comment is nil unless one was sent.
Dismiss reasonMeaning
close_buttonThe user tapped the close button.
backdropThe user tapped outside the message.
swipeThe user swiped it away.
appYour app closed it, for example with discardInAppMessages(dismissCurrent: true).
orientationThe device turned to an orientation the campaign doesn't allow. Not counted as a dismissal in the dashboard.

GrovsScreenTracking

protocolSince 3.0
Swift
public protocol GrovsScreenTracking {
    var grovsScreenName: String? { get }
}

Adopt on a UIViewController to name it for automatic screen tracking. Return nil to skip it.

GrovsScreenName

enumSince 3.0
Swift
public enum GrovsScreenName {
    case automatic
    case suppress
    case name(String)
}

Returned from screenNameProvider.

ValueEffect
.automaticFalls through to the SDK's resolution.
.suppressSkips the controller.
.name(_:)Overrides the name.

LogLevel

enumSince 3.0
Swift
public enum LogLevel: Int, Comparable {
    case info = 0
    case warn = 1
    case error = 2
}

Passed to setDebug.

ValueLogs
.infoEverything, including informational messages.
.warnWarnings and errors.
.errorErrors only (default).

TransactionType

enum
Swift
public enum TransactionType: String, Codable {
    case buy
    case cancel
    case refund
}

Used with logCustomPurchase.

CustomRedirects

type
Swift
public struct CustomRedirects: Codable {
    public var ios: CustomLinkRedirect?
    public var android: CustomLinkRedirect?
    public var desktop: CustomLinkRedirect?
 
    public init(ios: CustomLinkRedirect? = nil, android: CustomLinkRedirect? = nil, desktop: CustomLinkRedirect? = nil)
}

Per-platform redirect overrides for generateLink.

CustomLinkRedirect

type
Swift
public struct CustomLinkRedirect: Codable {
    public let link: String
    public var openAppIfInstalled: Bool
 
    public init(link: String, openAppIfInstalled: Bool = true)
}

One platform redirect. When openAppIfInstalled is true, the app opens if installed. Otherwise link is always used.

Closure types

TypeSignature
GrovsBoolCompletion(Bool) -> Void
GrovsURLClosure(URL?) -> Void
GrovsPayloadClosure([String: Any]?) -> Void
GrovsPayloadsClosure([[String: Any]]?) -> Void
GrovsLinkClosure([String: Any]?) -> Void
GrovsIntClosure(Int?) -> Void
GrovsEmptyClosure() -> Void
GrovsDeviceDataClosureClosure(Bool, [String: Any]?, String?, [String: Any]?) -> Void. Not used by any public method.

Extensions

GrovsNotificationServiceExtension

classSince 3.1
Swift
open class GrovsNotificationServiceExtension: UNNotificationServiceExtension {
    public var session: URLSession  // defaults to .shared
}

Shows campaign images in pushes. Make it the superclass of your Notification Service Extension's principal class.

  • In the GrovsNotificationService module (SPM product or pod). Safe to use from app extensions.
  • Downloads the image and attaches it if it's JPEG, PNG or GIF.
  • The push is delivered once, without the image if the download fails or time runs out.

GrovsNotificationContent

enumSince 3.1
Swift
public enum GrovsNotificationContent {
    public static let imageKey: String  // "grovs_image"
 
    @discardableResult
    public static func attachImage(to content: UNNotificationContent, session: URLSession = .shared,
                                   completion: @escaping (UNNotificationContent) -> Void) -> URLSessionTask?
 
    @discardableResult
    public static func attachImage(to request: UNNotificationRequest, session: URLSession = .shared,
                                   completion: @escaping (UNNotificationContent) -> Void) -> URLSessionTask?
}

Adds the campaign image to an existing extension's content, keeping your changes. In the GrovsNotificationService module.

Returns the download task, or nil when there's nothing to download.

  • completion runs once on a background queue, or right away when there's no image.
  • It gets the content unchanged when there's no image or it can't be shown.
  • Cancel the returned task in serviceExtensionTimeWillExpire(). The completion then runs without the image.

grovsScreen

methodSince 3.0
Swift
func grovsScreen(_ screenName: String, properties: [String: Any]? = nil) -> some View
func grovsScreen(properties: [String: Any]? = nil, fileID: String = #fileID) -> some View

SwiftUI modifier. Tracks a screen view when the view appears.

  • Suppresses automatic tracking for its hosting controller, so the screen is never counted twice.
  • The unnamed form uses the file name: CheckoutView.swift becomes "Checkout".

trackScreenView (modifier)

method
Swift
func trackScreenView(_ screenName: String, properties: [String: Any]? = nil) -> some View

SwiftUI modifier. Same as grovsScreen(_:properties:).


Deprecated

The messages inbox was removed in 3.1. These methods remain so existing code compiles, and show nothing. Use in-app messages.

displayMessagesViewController

methodDeprecated in 3.1
Swift
static func displayMessagesViewController(completion: GrovsEmptyClosure?)
static func displayMessagesViewController(completion: GrovsEmptyClosure?, onFailure: GrovsEmptyClosure?)

Shows nothing. Calls completion once on the main thread and never calls onFailure.

numberOfUnreadMessages

methodDeprecated in 3.1
Swift
static func numberOfUnreadMessages(completion: @escaping GrovsIntClosure)

Always yields 0, on the main thread.

Last updated 2026-10-27
Was this page helpful?