Note
The following integration instructions are relevant for SDK 3.0 or higher.
Follow our migration instructions to upgrade from SDK 2.x to 3.0 or refer to our 2.x integration instruction.
Important
SwiftUI codeless solution is fully supported from iOS 15
.
SwiftUI screen navigation tracking is available from iOS 13
.
Important
Requirements:
- Deployment target of
iOS 11
or higher - Swift Compatibility
5.7
or higher - Xcode
14
or higher
- Open the Podfile.
- Add:
pod 'Pendo'
.
- Open File -> Add Packages.
- Search for:
https://github.com/pendo-io/pendo-mobile-sdk
. - Select Up to Next Major Version.
Note
The API Key
can be found in your Pendo Subscription Settings in App Details.
Identify if your app project contains an AppDelegate
file or a SceneDelegate
file. Pure SwiftUI projects do not include either of these files. To use Pendo in your app, you will need to create one of them.
-
If using the
AppDelegate
file, implement the following:Swift Instructions - Click to expand or collapse
import UIKit import Pendo @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { PendoManager.shared().setup("YOUR_API_KEY_HERE") // your code here ... return true } }
Objective-C Instructions - Click to expand or collapse
#import "AppDelegate.h" #import "Pendo.h"; @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [[PendoManager sharedManager] setup:@"YOUR_API_KEY_HERE"]; // your code here ... return YES; } @end
-
If using the
SceneDelegate
file, implement the following:Swift Instructions - Click to expand or collapse
import Pendo func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { PendoManager.shared().setup("YOUR_API_KEY_HERE") // your code here ... }
Objective-C Instructions - Click to expand or collapse
#import "Pendo.h"; - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {} [[PendoManager sharedManager] setup:@"YOUR_API_KEY_HERE"]; // your code here ... }
To begin tracking a visitor's analytics and to display guides, call the startSession
API. The call to the startSession
API can be conducted immediately after calling the setup
API or anywhere else in the code, such as completing the login process of your app.
Swift Instructions - Click to expand or collapse
var visitorId = "John Doe"
var accountId = "ACME"
var visitorData: [String : any Hashable] = ["age": 27, "country": "USA"]
var accountData: [String : any Hashable] = ["Tier": 1, "size": "Enterprise"]
PendoManager.shared().startSession(visitorId, accountId:accountId, visitorData:visitorData, accountData:accountData)
Objective-C Instructions - Click to expand or collapse
[[PendoManager sharedManager] startSession:@"someVisitor" accountId:@"someAccount" visitorData:@{@"age": @27, @"country": @"USA"} accountData:@{@"Tier": @1, @"size": @"Enterprise"}];
Tip
To begin a session for an anonymous visitor, pass nil
or an empty string ""
as the visitor id. You can call the startSession
API more than once and transition from an anonymous session to an identified session (or even switch between multiple identified sessions).
If using SDK below 3.1 the pendoEnableSwiftUI()
modifier must be applied to the application rootView. If there are multiple rootViews (ex. usage of multiple UIHostingControllers), apply the modifier to each main rootView. See example below:
struct YourView: View {
var body: some View {
Text("RootView")
.pendoEnableSwiftUI()
}
}
Note
The Scheme ID
can be found in your Pendo Subscription Settings in App Details.
For additional information, see page tagging and guide testing.
Navigate to your App Target > Info > URL Types and create a new URL by clicking the plus (+) button.
Set the Identifier to pendo-pairing
or an identifiable name of your choosing.
Set URL Scheme to YOUR_SCHEME_ID_HERE
.
-
If using
AppDelegate
, add or modify theopenURL
function:Swift Instructions - Click to expand or collapse
import Pendo ... func application(_ app: UIApplication,open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { if url.scheme?.range(of: "pendo") != nil { PendoManager.shared().initWith(url) return true } // your code here... return true }
Objective-C Instructions - Click to expand or collapse
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options { if ([[url scheme] containsString:@"pendo"]) { [[PendoManager sharedManager] initWithUrl:url]; return YES; } //your code here... return YES; }
-
If using
SceneDelegate
, add or modify theopenURLContexts
function:Swift Instructions - Click to expand or collapse
import Pendo ... func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { if let url = URLContexts.first?.url, url.scheme?.range(of: "pendo") != nil { PendoManager.shared().initWith(url) } }
Objective-C Instructions - Click to expand or collapse
- (void)scene:(UIScene *)scene openURLContexts:(nonnull NSSet<UIOpenURLContext *> *)URLContexts { NSURL *url = [[URLContexts allObjects] firstObject].URL; if ([[url scheme] containsString:@"pendo"]) { [[PendoManager sharedManager] initWithUrl:url]; } // your code here ... }
If the entry point to your app is a struct
attributed with @main
, your SwiftUI application will not respond to the method application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool
.
To handle URL schemes in your SwiftUI app, add the .onOpenURL()
modifier to your main view.
import Pendo
@main
struct YourApp: App {
let persistenceController = PersistenceController.shared
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
return WindowGroup {
TabView {
YourView().tabItem {
Image("Icon")
Text("Text")
}
}
.pendoEnableSwiftUI()
.onOpenURL(perform: handleURL)
}
}
func handleURL(_ url: URL) {
_ = appDelegate.application(UIApplication.shared, open: url, options: [:])
}
}
- Test using Xcode:
Run the app while attached to Xcode.
Review the Xcode console and look for the following message:
Pendo Mobile SDK was successfully integrated and connected to the server.
- In the Pendo UI, go to Settings > Subscription Settings.
- Select the Applications tab and then your application.
- Select the Install Settings tab and follow the instructions under Verify Your Installation to ensure you have successfully integrated the Pendo SDK.
- Confirm that you can see your app as Integrated under subscription settings.
SwiftUI tracking of page changes is based on the application events emitted by the following navigation components: NavigationView
, TabView
, NavigationLink
, ActionSheet
, Sheets
or PopOvers
. Rendering new views on the page will not be tracked by our SDK.
Specific Limitations
-
List Elements: SwiftUI's handling of list elements can present limitations, particularly related to accessibility. If a list element has accessibility traits, it will be tracked by the SDK. However, if it does not, tracking might be incomplete or not occur at all. To ensure that list elements are properly tracked, make sure they have appropriate accessibility traits assigned.
-
Padding in Stacks: When using padding in
VStack
orHStack
without a background, the analytics tracking may not function correctly. This is because the padding alone doesn't generate trackable events. To work around this, you can explicitly call thependoRecognizeClickAnalytics()
API on the view to ensure that interactions are recorded. -
UIContextMenu: The UIContextMenu control is not supported in both Swift and SwiftUI. As a result, any interactions with context menus created using this control will not be tracked by the SDK.
-
API documentation available here.
-
Integration of native with Flutter components available here.
-
Sample apps with examples of feature tagging and how Pendo analytics work.
(pay attention to comments with PENDO CHANGE. In some cases these require minor changes of integration code or adding a background color)
Why aren't some elements being tagged correctly in SwiftUI?
-
Missing Accessibility Traits - Ensure that interactive elements, like buttons, have appropriate accessibility traits (e.g., .button). Adding these traits helps our SDK recognize and tag them correctly.
-
Embedding SwiftUI in UIKit - If you are using SwiftUI elements inside UIKit, enable
pendoOptions.enableSwiftUIInsideUIKitScan
. This option will help our SDK to recognize SwiftUI components within UIKit containers. -
Using Our API -
pendoRecognizeClickAnalytics()
- Even with codeless solutions, sometimes it’s necessary to use our tagging API to manually recognize clickable views. Applying this API to the specific view can resolve tagging issues effectively.
Why do some of my SwiftUI screens have generic or irrelevant keywords in their screenId, and how can this be improved?
- While we continue to refine screen identification for SwiftUI, make sure that your SwiftUI views are properly structured and identifiable. For now, this may require some manual adjustments to ensure each screen is tracked correctly.
I have noticed performance issues in my app after integrating Pendo SDK. What should I do?
-
Disable Unnecessary Information Collection - To improve performance, particularly on iPads, consider disabling some of the things Pendo collects while scanning your page:
- Texts Collection - Set enableTextCollectionSwiftUI to false in pendoOptions:
let options = PendoOptions() options.configs = ["enableTextCollectionSwiftUI": false] PendoManager.shared().setup(prodAppKey, with: options)
- Pruning - To save time during scanning, set pendoOptions.enablePruning = false. This may help reduce the overhead.
-
Optimizing Scanning Depth - If performance issues persist, adjust the scan depth settings. Consult our support team to configure this setting for optimal performance.
- For technical issues, please review open issues or submit a new issue.
- Release notes can be found here.
- For additional documentation, visit our Help Center Mobile Section.