{"id":32147283,"url":"https://github.com/devrev/devrev-sdk-ios","last_synced_at":"2026-04-27T03:00:59.153Z","repository":{"id":197959131,"uuid":"598191199","full_name":"devrev/devrev-sdk-ios","owner":"devrev","description":"DevRev SDK, used for integrating DevRev services into your iOS app.","archived":false,"fork":false,"pushed_at":"2026-04-10T09:12:42.000Z","size":934141,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":6,"default_branch":"main","last_synced_at":"2026-04-10T11:23:26.631Z","etag":null,"topics":["analytics","apple","chat","framework","ios","ipados","library","mobile","mobile-sdk","objective-c","observability","support","swift"],"latest_commit_sha":null,"homepage":"https://devrev.github.io/devrev-sdk-ios/","language":"Swift","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/devrev.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-02-06T15:40:24.000Z","updated_at":"2026-04-10T09:12:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"b4a76bb8-fc1b-45f6-a3bd-6ab119f53416","html_url":"https://github.com/devrev/devrev-sdk-ios","commit_stats":null,"previous_names":["devrev/devrev-sdk-ios"],"tags_count":41,"template":false,"template_full_name":null,"purl":"pkg:github/devrev/devrev-sdk-ios","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devrev%2Fdevrev-sdk-ios","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devrev%2Fdevrev-sdk-ios/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devrev%2Fdevrev-sdk-ios/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devrev%2Fdevrev-sdk-ios/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/devrev","download_url":"https://codeload.github.com/devrev/devrev-sdk-ios/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devrev%2Fdevrev-sdk-ios/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32320683,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T23:26:28.701Z","status":"online","status_checked_at":"2026-04-27T02:00:06.769Z","response_time":128,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["analytics","apple","chat","framework","ios","ipados","library","mobile","mobile-sdk","objective-c","observability","support","swift"],"created_at":"2025-10-21T08:59:53.939Z","updated_at":"2026-04-27T03:00:59.140Z","avatar_url":"https://github.com/devrev.png","language":"Swift","readme":"# DevRev SDK for iOS\nDevRev SDK, used for integrating DevRev services into your iOS app.\n\n- [DevRev SDK for iOS](#devrev-sdk-for-ios)\n\t- [Quickstart](#quickstart)\n\t\t- [Requirements](#requirements)\n\t\t- [Integration](#integration)\n\t\t\t- [Swift Package Manager (Recommended)](#swift-package-manager-recommended)\n\t\t\t- [CocoaPods](#cocoapods)\n\t\t- [Set up the DevRev SDK](#set-up-the-devrev-sdk)\n\t\t\t- [Update the feature configuration](#update-the-feature-configuration)\n\t\t\t- [Feature configuration reference](#feature-configuration-reference)\n\t\t\t\t- [Configuration caching](#configuration-caching)\n\t\t\t\t- [Support widget theme options](#support-widget-theme-options)\n\t- [Features](#features)\n\t\t- [Identification](#identification)\n\t\t\t- [Identify an unverified user](#identify-an-unverified-user)\n\t\t\t- [Identify a verified user](#identify-a-verified-user)\n\t\t\t\t- [Generate an AAT](#generate-an-aat)\n\t\t\t\t- [Exchange your AAT for a session token](#exchange-your-aat-for-a-session-token)\n\t\t\t\t- [Identify the verified user](#identify-the-verified-user)\n\t\t\t- [Update the user](#update-the-user)\n\t\t\t- [Logout](#logout)\n\t\t\t- [Identity model](#identity-model)\n\t\t\t\t- [Properties](#properties)\n\t\t\t\t- [User traits](#user-traits)\n\t\t\t\t- [Organization traits](#organization-traits)\n\t\t\t\t- [Account traits](#account-traits)\n\t\t- [Support chat](#support-chat)\n\t\t\t- [UIKit](#uikit)\n\t\t\t- [SwiftUI](#swiftui)\n\t\t- [Create a new support conversation](#create-a-new-support-conversation)\n\t\t- [New conversation closure](#new-conversation-closure)\n\t\t- [In-app link handling](#in-app-link-handling)\n\t\t- [Dynamic theme configuration](#dynamic-theme-configuration)\n\t\t- [PLuG article search filters](#plug-article-search-filters)\n\t\t- [Analytics](#analytics)\n\t\t- [Session analytics](#session-analytics)\n\t\t\t- [Opt in or out](#opt-in-or-out)\n\t\t\t- [Session recording](#session-recording)\n\t\t\t- [Session properties](#session-properties)\n\t\t\t- [Masking sensitive data](#masking-sensitive-data)\n\t\t\t- [Custom masking provider](#custom-masking-provider)\n\t\t\t- [User interaction tracking](#user-interaction-tracking)\n\t\t\t- [Timers](#timers)\n\t\t\t- [Capture errors](#capture-errors)\n\t\t\t- [Track screens](#track-screens)\n\t\t- [Push notifications](#push-notifications)\n\t\t\t- [Configuration](#configuration)\n\t\t\t- [Register for push notifications](#register-for-push-notifications)\n\t\t\t- [Unregister from push notifications](#unregister-from-push-notifications)\n\t\t\t- [Handle push notifications](#handle-push-notifications)\n\t- [Sample app](#sample-app)\n\t- [Troubleshooting](#troubleshooting)\n\t- [Migration guide](#migration-guide)\n\n## Quickstart\n\n### Requirements\n\n- Xcode 16.0 or later (latest stable version available on the App Store).\n- Swift 5.9 or later.\n- The minimum deployment target should be 15.0.\n- Recommended: An SSH key configured locally and registered with [GitHub](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh).\n\n### Integration\nThe DevRev SDK can be integrated using either Swift Package Manager (SPM) or CocoaPods.\n\n\u003e [!CAUTION]\n\u003e We recommend integrating the DevRev SDK using Swift Package Manager and SSH. CocoaPods is in [maintenance mode](https://blog.cocoapods.org/CocoaPods-Support-Plans/) since August 2024 and will be [deprecated in the future](https://blog.cocoapods.org/CocoaPods-Specs-Repo/).\n\n#### Swift Package Manager (Recommended)\n\nTo integrate the DevRev SDK into your project using SPM:\n\n1. Open your project in Xcode and go to the **Add Package Dependency**.\n2. Enter the DevRev SDK URL under **Enter Package URL**:\n\t- For SSH: `git@github.com:devrev/devrev-sdk-ios.git` (recommended)\n\t- For HTTPS: https://github.com/devrev/devrev-sdk-ios\n3. In the **Build Phases** section of your app target, locate the **Link Binary With Libraries** phase and confirm that `DevRevSDK` is linked. If not, add it by clicking **+** and selecting `DevRevSDK` from the list.\n\nNow you should be able to import and use the DevRev SDK in your project.\n\n#### CocoaPods\n\nTo integrate the DevRev SDK using CocoaPods:\n\n1. Add the following to your `Podfile`:\n\t```ruby\n\tpod 'DevRevSDK', '~\u003e \u003cVERSION\u003e'\n\t```\n2. Run `pod install` in your project directory.\n\nThis will install the DevRev SDK in your project, making it ready for use.\n\n### Set up the DevRev SDK\n\n1. Open the DevRev web app at [https://app.devrev.ai](https://app.devrev.ai) and go to the **Settings** page.\n2. Under **PLuG settings** copy the value under **Your unique App ID**.\n3. Configure the DevRev SDK in your app using the obtained credentials.\n\n\u003e [!CAUTION]\n\u003e The DevRev SDK must be configured before you can use any of its features.\n\nThe SDK becomes ready for use once the configuration API is executed. Remote configuration is fetched from the backend and cached locally. On subsequent launches, you can use the cached configuration to avoid a network round-trip and speed up cold start (see [Configuration caching](#configuration-caching)).\n\n```swift\nDevRev.configure(appID:)\n```\n\nTo provide a feature configuration during setup, call the overload that accepts it:\n\n```swift\nDevRev.configure(appID:featureConfiguration:)\n```\n\nFor default behavior, call the simpler overload:\n\n```swift\nDevRev.configure(appID: \"abcdefg12345\")\n```\n\nTo customize behavior such as frame capture, auto-start recording, configuration caching, or theme preferences, pass a `FeatureConfiguration` instance:\n\n```swift\nDevRev.configure(\n\tappID: \"abcdefg12345\",\n\tfeatureConfiguration: FeatureConfiguration(\n\t\tenableFrameCapture: false,\n\t\tautoStartRecording: false,\n\t\talwaysUseRemoteConfig: true,\n\t\tsupportWidgetTheme: .systemDefault,\n\t\tenableSupportChatStreaming: false\n\t)\n)\n```\n\n#### Update the feature configuration\n\nYou can adjust the feature configuration without reconfiguring the SDK:\n\n```swift\nDevRev.updateFeatureConfiguration(\n\tFeatureConfiguration(\n\t\tenableFrameCapture: true,\n\t\tautoStartRecording: true,\n\t\talwaysUseRemoteConfig: true,\n\t\tsupportWidgetTheme: .systemDefault,\n\t\tenableSupportChatStreaming: false\n\t)\n)\n```\n\n#### Feature configuration reference\n\n`FeatureConfiguration` controls how the SDK behaves both during initial setup and when calling `DevRev.updateFeatureConfiguration(_:)`.\n\n```swift\nlet configuration = FeatureConfiguration.default\n```\n\n| Property | Type | Default | Description |\n|----------|------|---------|-------------|\n| `enableFrameCapture` | `Bool` | `true` | Enables the screen capture pipeline used by session replay. |\n| `autoStartRecording` | `Bool` | `true` | Automatically starts recording after the SDK finishes remote configuration (or when using cached config). |\n| `alwaysUseRemoteConfig` | `Bool` | `true` | When `true`, the SDK always fetches remote configuration at startup and when the app enters background. When `false`, the SDK uses cached configuration when available and skips the remote fetch, improving cold start. |\n| `supportWidgetTheme` | `SupportWidgetTheme` | `.systemDefault` | Controls the appearance of the in-app support widget, including dynamic theme behavior. |\n| `enableSupportChatStreaming` | `Bool` | `false` | When `true`, enables real-time AI agent response streaming in PLuG conversations (WebSocket streaming, optimistic UI, animated text). |\n| `supportWidgetArticleSearchFilters` | `ArticleSearchFilters?` | `nil` | Optional filters for PLuG article search (widget and CMDK). Applied automatically when the support widget is ready. |\n\nUse the designated initializer to override any combination of options:\n\n```swift\nlet configuration = FeatureConfiguration(\n\tenableFrameCapture: false,\n\tautoStartRecording: false,\n\talwaysUseRemoteConfig: false,\n\tsupportWidgetTheme: .systemDefault,\n\tenableSupportChatStreaming: true,\n\tarticleSearchFilters: myFilters\n)\n```\n\nWhen you only need to toggle frame capture while preserving the current runtime values for other options, use the convenience initializer:\n\n```swift\nDevRev.updateFeatureConfiguration(\n\t.init(withShouldEnableFrameCapture: false)\n)\n```\n\nWhen you only need to change the support widget theme, use the convenience initializer that preserves the current values for other options:\n\n```swift\nDevRev.updateFeatureConfiguration(\n\t.init(witCustomSupportWidgetTheme: .systemDefault)\n)\n```\n\n##### Configuration caching\n\nWhen `alwaysUseRemoteConfig` is `false`, the SDK uses the last successfully fetched configuration stored on the device. If a cached configuration exists, the SDK skips the remote config request at startup and applies the cached settings (e.g. session replay, observability). This reduces cold-start latency and allows the app to work offline with the last known config. The first launch (or after clearing app data) still performs a remote fetch when network is available. Set `alwaysUseRemoteConfig: true` (the default) to retain the previous behavior of always fetching remote configuration at startup and when the app enters background.\n\n##### Support widget theme options\n\n`SupportWidgetTheme` lets you fine-tune the support UI. Start from `.systemDefault` or provide explicit values:\n\n```swift\nlet customTheme = SupportWidgetTheme(\n\tprefersSystemTheme: false,\n\tprimaryTextColor: \"#1F2933\",\n\taccentColor: \"#F97316\",\n\tspacing: [\n\t\t\"bottom\": \"20px\",\n\t\t\"side\": \"16px\"\n\t]\n)\n```\n\n| Property | Type | Default | Description |\n|----------|------|---------|-------------|\n| `prefersSystemTheme` | `Bool` | `true` | Follows the device appearance when `true`; otherwise uses your custom colors. |\n| `primaryTextColor` | `String?` | `nil` | Hex or RGB value for primary text in the support widget. |\n| `accentColor` | `String?` | `nil` | Hex or RGB value applied to buttons and highlights. |\n| `spacing` | `[String: String]?` | `nil` | CSS-like spacing overrides (`\"bottom\"` and `\"side\"` keys are recognized). |\n\n- UIKit apps\n\nConfigure the SDK in the `AppDelegate.application(_:didFinishLaunchingWithOptions:)` method.\n\n- SwiftUI apps\n\nDepending on your app's architecture, configure the SDK at the app's entry point or initial view.\n\n## Features\n\n### Identification\n\nTo access certain features of the DevRev SDK, user identification is required.\n\nThe identification function should be placed appropriately in your app after the user logs in. If you have the user information available at app launch, call the function after your `DevRev.configure` call has completed.\n\n\u003e [!TIP]\n\u003e If you haven't previously identified the user, the DevRev SDK will automatically create an anonymous user for you immediately after the SDK is configured.\n\n\u003e [!TIP]\n\u003e The `Identity` structure allows for custom fields in the user, organization, and account traits. These fields must be configured through the DevRev app before they can be utilized. For more information, refer to [Object customization](https://devrev.ai/docs/product/object-customization).\n\nYou can select from the following methods to identify users within your application:\n\n#### Identify an unverified user\n\nThe unverified identification method identifies users with a unique identifier, but it does not verify their identity with the DevRev backend.\n\n```swift\nDevRev.identifyUnverifiedUser(_:)\n```\n\nThe function accepts the `DevRev.Identity` structure, with the user identifier (`userID`) as the only required property, all other properties are optional.\n\n#### Identify a verified user\n\nThe verified identification method is used to identify users with an identifier unique to your system within the DevRev platform. The verification is done through a token exchange process between you and the DevRev backend.\n\nThe steps to identify a verified user are as follows:\n1. Generate an AAT for your system (preferably through your backend).\n2. Exchange your AAT for a session token for each user of your system.\n3. Pass the user identifier and the exchanged session token to the `DevRev.identifyVerifiedUser(_:sessionToken:)` method.\n\n\u003e [!CAUTION]\n\u003e For security reasons, it is **strongly recommended** that the token exchange is executed on your backend to prevent exposing your application access token (AAT).\n\n##### Generate an AAT\n\n1. Open the DevRev web app at [https://app.devrev.ai](https://app.devrev.ai) and go to the **Settings** page.\n2. Open the **PLuG Tokens** page.\n3. Under the **Application access tokens** panel, click **New token** and copy the token that's displayed.\n\n\u003e [!CAUTION]\n\u003e Ensure that you copy the generated application access token, as you cannot view it again.\n\n##### Exchange your AAT for a session token\n\nTo proceed with identifying the user, you need to exchange your AAT for a session token. This step helps you identify a user of your own system within the DevRev platform.\n\nHere is a simple example of an API request to the DevRev backend to exchange your AAT for a session token:\n\n\u003e [!CAUTION]\n\u003e Make sure that you replace the `\u003cAAT\u003e` and `\u003cYOUR_USER_ID\u003e` with the actual values.\n\n```bash\ncurl \\\n--location 'https://api.devrev.ai/auth-tokens.create' \\\n--header 'accept: application/json, text/plain, */*' \\\n--header 'content-type: application/json' \\\n--header 'authorization: \u003cAAT\u003e' \\\n--data '{\n  \"rev_info\": {\n    \"user_ref\": \"\u003cYOUR_USER_ID\u003e\"\n  }\n}'\n```\n\nThe response of the API call contains a session token that you can use with the verified identification method in your app.\n\n\u003e [!CAUTION]\n\u003e As a good practice, **your** app should retrieve the exchanged session token from **your** backend at app launch or any relevant app lifecycle event.\n\n##### Identify the verified user\n\nPass the user identifier and the exchanged session token to the verified identification method:\n\n```swift\nDevRev.identifyVerifiedUser(_:sessionToken:)\n```\n\n#### Update the user\n\nYou can update the user's information using the following method:\n\n```swift\nDevRev.updateUser(_:)\n```\n\nThis function accepts the `DevRev.Identity` structure.\n\n\u003e [!CAUTION]\n\u003e The `userID` property cannot be updated.\n\n\u003e [!TIP]\n\u003e The identification functions are asynchronous. Ensure you wrap them in a `Task` when calling from synchronous contexts.\n\nUse this property to check whether the user is identified in the current session:\n\n```swift\nDevRev.isUserIdentified\n```\n\n#### Logout\n\nYou can perform a logout of the current user by calling the following method:\n\n```swift\nDevRev.logout(deviceID:)\n```\n\nThe user is logged out by clearing their credentials, as well as unregistering the device from receiving push notifications, and stopping the session recording.\n\nFor example:\n\n```swift\n// Identify an unverified user using their email address as the user identifier.\nawait DevRev.identifyUnverifiedUser(Identity(userID: \"user@example.org\"))\n\n// Identify a verified user using their email address as the user identifier.\nawait DevRev.identifyVerifiedUser(\"foo@example.org\", sessionToken: \"bar-1337\")\n\n// Update the user's information.\nawait DevRev.updateUser(Identity(organizationID: \"organization-1337\"))\n\n// Logout the identified user.\nawait DevRev.logout(deviceID: \"dvc32423\")\n```\n\n#### Identity model\n\nThe `Identity` class is used to provide user, organization, and account information when identifying users or updating their details. This class is used primarily with the `identifyUnverifiedUser(_:)` and `updateUser(_:)` methods.\n\n##### Properties\n\nThe `Identity` class contains the following properties:\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| `userID` | `String` | ✅ | A unique identifier for the user |\n| `organizationID` | `String?` | ❌ | An identifier for the user's organization |\n| `accountID` | `String?` | ❌ | An identifier for the user's account |\n| `userTraits` | `UserTraits?` | ❌ | Additional information about the user |\n| `organizationTraits` | `OrganizationTraits?` | ❌ | Additional information about the organization |\n| `accountTraits` | `AccountTraits?` | ❌ | Additional information about the account |\n\n\u003e [!NOTE]\n\u003e The custom fields properties defined as part of the user, organization and account traits, must be configured in the DevRev web app **before** they can be used. See [Object customization](https://devrev.ai/docs/product/object-customization) for more information.\n\n##### User traits\n\nThe `UserTraits` class contains detailed information about the user:\n\n\u003e [!NOTE]\n\u003e All properties in `UserTraits` are optional.\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `displayName` | `String?` | The displayed name of the user |\n| `email` | `String?` | The user's email address |\n| `fullName` | `String?` | The user's full name |\n| `userDescription` | `String?` | A description of the user |\n| `phoneNumbers` | `[String]?` | Array of the user's phone numbers |\n| `customFields` | `[String: Any]?` | Dictionary of custom fields configured in DevRev |\n\n##### Organization traits\n\nThe `OrganizationTraits` class contains detailed information about the organization:\n\n\u003e [!NOTE]\n\u003e All properties in `OrganizationTraits` are optional.\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `displayName` | `String?` | The displayed name of the organization |\n| `domain` | `String?` | The organization's domain |\n| `organizationDescription` | `String?` | A description of the organization |\n| `phoneNumbers` | `[String]?` | Array of the organization's phone numbers |\n| `tier` | `String?` | The organization's tier or plan level |\n| `customFields` | `[String: Any]?` | Dictionary of custom fields configured in DevRev |\n\n##### Account traits\n\nThe `AccountTraits` class contains detailed information about the account:\n\n\u003e [!NOTE]\n\u003e All properties in `AccountTraits` are optional.\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `displayName` | `String?` | The displayed name of the account |\n| `domains` | `[String]?` | Array of domains associated with the account |\n| `accountDescription` | `String?` | A description of the account |\n| `phoneNumbers` | `[String]?` | Array of the account's phone numbers |\n| `websites` | `[String]?` | Array of websites associated with the account |\n| `tier` | `String?` | The account's tier or plan level |\n| `customFields` | `[String: Any]?` | Dictionary of custom fields configured in DevRev |\n\n### Support chat\n\n#### UIKit\n\nThe support chat feature can be shown as a modal screen from a specific view controller or the top-most one, or can be pushed onto a navigation stack.\n\nTo show the support chat screen in your app, you can use the following overloaded method:\n\n```swift\nDevRev.showSupport(from:isAnimated:)\n```\n\n- When a `UIViewController` is passed as the `from` parameter, the screen is shown modally.\n\n- When a `UINavigationController` is passed as the `from` parameter, the screen is pushed onto the navigation stack.\n\nIf you want to display the support chat screen from the top-most view controller, use the following method:\n\n```swift\nDevRev.showSupport(isAnimated:)\n```\n\nFor example:\n\n```swift\n// Push the support chat screen to a navigation stack.\nawait DevRev.showSupport(from: mainNavigationController)\n\n// Show the support chat screen modally from a specific view controller.\nawait DevRev.showSupport(from: settingsViewController)\n\n// Show the support chat screen from the top-most view controller, without an animation.\nawait DevRev.showSupport(isAnimated: false)\n```\n\n#### SwiftUI\n\nTo display the support chat screen in a SwiftUI app, you can use the following view:\n\n```swift\nDevRev.supportView\n```\n\n### Create a new support conversation\n\nYou can initiate a new support conversation directly from your app. This method displays the support chat screen and simultaneously creates a new conversation.\n\n```swift\nDevRev.createSupportConversation(isAnimated:)\n```\n\nFor example:\n\n```swift\n// Create a new support conversation directly from the top-most view controller.\nawait DevRev.createSupportConversation(isAnimated: true)\n```\n\n### New conversation closure\n\nYou can receive a callback when a user creates a new conversation by setting the following closure:\n\n```swift\nDevRev.conversationCreatedCompletion\n```\n\nThis allows your app to access the ID of the newly created conversation.\n\nFor example:\n\n```swift\nDevRev.conversationCreatedCompletion = { conversationID in\n\tprint(\"A new conversation has been created: \\(conversationID).\")\n}\n```\n\n### In-app link handling\n\nThe DevRev SDK provides a mechanism to handle links opened from within any screen that is part of the DevRev SDK.\n\nYou can fully customize the link handling behavior by setting the specialized in-app link handler. That way you can decide what should happen when a link is opened from within the app.\n\n```swift\nDevRev.inAppLinkHandler: ((URL) -\u003e Void)?\n```\n\nYou can further customize the behavior by setting the `shouldDismissModalsOnOpenLink` boolean flag. This flag controls whether the DevRev SDK should dismiss the top-most modal screen when a link is opened.\n\n```swift\nDevRev.shouldDismissModalsOnOpenLink: Bool\n```\n\n### Dynamic theme configuration\n\nThe DevRev SDK allows you to configure the theme dynamically based on the system appearance, or use the theme configured on the DevRev portal. By default, the theme is dynamic and follows the system appearance.\n\nUse `SupportWidgetTheme` inside your `FeatureConfiguration` to align the support experience with your brand:\n\n```swift\nDevRev.updateFeatureConfiguration(\n\tFeatureConfiguration(\n\t\tenableFrameCapture: true,\n\t\tautoStartRecording: true,\n\t\talwaysUseRemoteConfig: true,\n\t\tsupportWidgetTheme: SupportWidgetTheme(\n\t\t\tprefersSystemTheme: false,\n\t\t\tprimaryTextColor: \"#202020\",\n\t\t\taccentColor: \"#34C759\"\n\t\t),\n\t\tenableSupportChatStreaming: true\n\t)\n)\n```\n\n\u003e [!CAUTION]\n\u003e Directly mutating `DevRev.prefersSystemTheme` is maintained only for backward compatibility and is deprecated. Prefer configuring the theme through `SupportWidgetTheme` passed via `FeatureConfiguration`.\n\n### PLuG article search filters\n\nSet `FeatureConfiguration.supportWidgetArticleSearchFilters` to control which articles are returned by PLuG search (widget search and CMDK search). Filters are applied automatically when the support widget is ready.\n\nUse `ArticleSearchFilters` to set separate filters for widget search (`widgetSearch`) and CMDK search (`searchBarSearch`). Each filter uses DQL-style expressions with an operator (`op`) and `operands` (field, op, value, valueType). Use `ArticleSearchFilterOperator` cases such as `.and`, `.or`, `.in`, `.eq`, `.ne`, `.gt`, `.gte`, `.lt`, `.lte` (plus other backend-supported operators), and `ArticleSearchFilterOperandValueType` (`.json` or `.part`) for each operand’s `valueType`.\n\nExample:\n\n```swift\nlet filters = ArticleSearchFilters(\n    widgetSearch: ArticleSearchFilter(\n        op: .and,\n        operands: [\n            ArticleSearchFilterOperand(\n                field: \"article.tags.tag_id\",\n                op: .in,\n                value: .stringArray([\"don:core:dvrv-us-1:devo/1T6yo cw2Y9:tag/32\"]),\n                valueType: .json\n            )\n        ]\n    ),\n    searchBarSearch: ArticleSearchFilter(\n        op: .and,\n        operands: [\n            ArticleSearchFilterOperand(\n                field: \"article.tags.tag_id\",\n                op: .ne,\n                value: .stringArray([\"don:core:dvrv-us-1:devo/1T6yo cw2Y9:tag/32\"]),\n                valueType: .json\n            )\n        ]\n    )\n)\nDevRev.configure(\n    appID: appID,\n    featureConfiguration: FeatureConfiguration(\n        enableFrameCapture: true,\n        autoStartRecording: true,\n        alwaysUseRemoteConfig: true,\n        supportWidgetTheme: .systemDefault,\n        supportWidgetArticleSearchFilters: filters\n    )\n)\n```\n\nTo filter only one surface, pass a filter for that surface only (e.g. `ArticleSearchFilters(widgetSearch: someFilter, searchBarSearch: nil)`). Pass `nil` for `supportWidgetArticleSearchFilters` for no filter.\n\n\u003e [!NOTE]\n\u003e For the AI agent on the conversation page to use the same filtered article set, configure the Hybrid Search snap-in and attach it to the agent’s skills in the DevRev app, and include the required filters in the search query. See [DevRev docs](https://devrev.ai/docs) for snap-in setup.\n\n### Analytics\n\nThe DevRev SDK allows you to send custom analytic events by using a name and a string dictionary. You can track these events using the following function:\n\n```swift\nDevRev.trackEvent(name:properties:)\n```\n\nFor example:\n\n```swift\nawait DevRev.trackEvent(name: \"open-message-screen\", properties: [\"id\": \"message-1337\"])\n```\n\n### Session analytics\n\nThe DevRev SDK offers session analytics features to help you understand how users interact with your app.\n\n#### Opt in or out\n\nSession analytics features are opted-in by default, enabling them from the start. However, you can opt-out using the following method:\n\n```swift\nDevRev.stopAllMonitoring()\n```\n\nTo opt back in, use the following method:\n\n```swift\nDevRev.resumeAllMonitoring()\n```\n\n#### Session recording\n\nYou can enable session recording to capture user interactions with your app.\n\n\u003e [!NOTE]\n\u003e The session recording feature is opt-out and is enabled by default.\n\nThe session recording feature includes the following methods to control the recording:\n\n| Method                                                               | Action                                                    |\n|--------------------------------------------------------------------|-----------------------------------------------------------|\n|`DevRev.startRecording()`   | Starts the session recording.                             |\n|`DevRev.stopRecording()`    | Ends the session recording and uploads it to the portal. |\n|`DevRev.pauseRecording()`   | Pauses the ongoing session recording.                     |\n|`DevRev.resumeRecording()`  | Resumes a paused session recording.                       |\n|`DevRev.processAllOnDemandSessions()`  | Stops the ongoing user recording and sends all on-demand sessions along with the current recording. |\n\nYou can also check the following flags for session recording:\n\n```swift\n// Check if session recording is currently active.\nlet isRecording = DevRev.isRecording\n\n// Check if session monitoring is enabled.\nlet isMonitoringEnabled = DevRev.isMonitoringEnabled\n\n// Check if on-demand sessions are enabled.\nlet areOnDemandSessionsEnabled = DevRev.areOnDemandSessionsEnabled\n```\n\n#### Session properties\n\nYou can add custom properties to the session recording to help you understand the context of the session. The properties are defined as a dictionary of string values.\n\n```swift\nDevRev.addSessionProperties(_:)\n```\n\nTo clear the session properties in scenarios such as user logout or when the session ends, use the following method:\n\n```swift\nDevRev.clearSessionProperties()\n```\n\n#### Masking sensitive data\n\nTo protect sensitive data, the DevRev SDK provides an auto-masking feature that masks data before sending to the server. Input views such as text fields, text views, and web views are automatically masked.\n\nWhile the auto-masking feature may be sufficient for most situations, you can manually mark additional views as sensitive using the following method:\n\n```swift\nDevRev.markSensitiveViews(_:)\n```\n\nIf any previously masked views need to be unmasked, you can use the following method:\n\n```swift\nDevRev.unmarkSensitiveViews(_:)\n```\n\n#### Custom masking provider\n\nFor advanced use cases, you can provide a custom masking provider to specify exactly which regions of the UI should be masked in snapshots.\n\nYou can implement your own masking logic by conforming to the `DevRev.MaskLocationProviding` protocol and setting your custom object as the masking provider. This allows you to specify explicit regions to be masked or to skip snapshots entirely.\n\n| Symbol | Description |\n|-|-|\n|`DevRev.setMaskingLocationProvider(_ provider: DevRev.MaskLocationProviding)`|A custom provider that determines which UI regions should be masked for privacy during snapshots.|\n|`DevRev.MaskLocationProviding`|A protocol for providing explicit masking locations for UI snapshots.|\n|`DevRev.SnapshotMask`|An object that describes the regions of a snapshot to be masked.|\n|`DevRev.SnapshotMask.Location`|An object that describes a masked region.|\n\nFor example:\n\n```swift\nimport Foundation\nimport UIKit\nimport DevRevSDK\n\nclass MyMaskingProvider: NSObject, DevRev.MaskLocationProviding {\n\tfunc provideSnapshotMask() async -\u003e DevRev.SnapshotMask {\n        let region = CGRect(x: 10, y: 10, width: 100, height: 40)\n        let location = DevRev.SnapshotMask.Location(location: region)\n        let mask = DevRev.SnapshotMask(locations: [location], shouldSkip: false)\n\t\treturn mask\n\t}\n}\n```\n\n```swift\nDevRev.setMaskingLocationProvider(MyMaskingProvider())\n```\n\n\u003e [!TIP]\n\u003e Setting a new provider overrides any previously set masking location provider.\n\n#### User interaction tracking\n\nThe DevRev SDK automatically tracks user interactions such as taps, swipes, and scrolls. However, in some cases you may want to disable this tracking to prevent sensitive user actions from being recorded.\n\nTo **temporarily disable** user interaction tracking, use the following method:\n\n```swift\nDevRev.pauseUserInteractionTracking()\n```\n\nTo **resume** user interaction tracking, use the following method:\n```swift\nDevRev.resumeUserInteractionTracking()\n```\n\n#### Timers\n\nThe DevRev SDK offers a timer mechanism to measure the time spent on specific tasks, allowing you to track events such as response time, loading time, or any other duration-based metrics.\n\nThe mechanism works using balanced start and stop methods that both accept a timer name and an optional dictionary of properties.\n\nTo start a timer, use the following method:\n\n```swift\nDevRev.startTimer(_:properties:)\n```\n\nTo stop a timer, use the following method:\n\n```swift\nDevRev.endTimer(_:properties:)\n```\n\nFor example:\n\n```swift\nDevRev.startTimer(\"response-time\", properties: [\"id\": \"task-1337\"])\n\n// Perform the task that you want to measure.\n\nDevRev.endTimer(\"response-time\", properties: [\"id\": \"task-1337\"])\n```\n\n#### Capture errors\n\nYou can report a handled error from a catch block using the `captureError` function.\n\nThis ensures that even if the error is handled in your app, it will still be logged for diagnostics.\n\n```swift\nDevRev.captureError(\n    _ error: Error,\n    tag: String\n)\n```\n\n**Example:**\n\n```swift\ndo {\n    try someFunction()\n} catch {\n    DevRev.captureError(\n        error,\n        tag: \"network-failure\"\n    )\n}\n```\n\n#### Track screens\n\nThe DevRev SDK offers automatic screen tracking to help you understand how users navigate through your app. Although view controllers are automatically tracked, you can manually track screens using the following method:\n\n```swift\nDevRev.trackScreenName(_:)\n```\n\nFor example:\n\n```swift\nDevRev.trackScreenName(\"profile-screen\")\n```\n\n### Push notifications\n\nYou can configure your app to receive push notifications from the DevRev SDK. The SDK is designed to handle push notifications and execute actions based on the notification's content.\n\nThe DevRev backend sends push notifications to your app to notify users about new messages in the support chat.\n\n#### Configuration\n\nTo receive push notifications, you need to configure your DevRev organization by following the instructions in the [push notifications](https://developer.devrev.ai/sdks/mobile/push-notifications) section.\n\nYou need to ensure that your iOS app is configured to receive push notifications. You can follow the [Apple documentation](https://developer.apple.com/documentation/usernotifications/registering_your_app_with_apns) for guidance on registering your app with Apple Push Notification service (APNs).\n\n#### Register for push notifications\n\n\u003e [!TIP]\n\u003e Push notifications require that the SDK has been configured and the user has been identified (unverified and verified users). The user identification is required to send the push notification to the correct user.\n\nThe DevRev SDK offers a method to register your device for receiving push notifications. You can register for push notifications using the following method:\n\n```swift\nDevRev.registerDeviceToken(_:deviceID:)\n```\n\nThe method requires a device identifier, which can either be an identifier unique to your system or the Apple-provided Vendor Identifier (IDFV). Typically, the token registration is called from the `AppDelegate.application(_:didRegisterForRemoteNotificationsWithDeviceToken:)` method.\n\nFor example:\n\n```swift\nfunc application(\n\t_ application: UIApplication,\n\tdidRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data\n) {\n\tguard\n\t\tlet deviceID = UIDevice.current.identifierForVendor?.uuidString\n\telse {\n\t\treturn\n\t}\n\n\tTask {\n\t\tawait DevRev.registerDeviceToken(\n\t\t\tdeviceToken,\n\t\t\tdeviceID: deviceID\n\t\t)\n\t}\n}\n```\n\n#### Unregister from push notifications\n\nIf your app no longer needs to receive push notifications, you can unregister the device.\n\nUse the following method to unregister the device:\n\n```swift\nDevRev.unregisterDevice(_:)\n```\n\nThis method requires the device identifier, which should be the same as the one used during registration. It is recommended to place this method after calling `UIApplication.unregisterForRemoteNotifications()` in your app.\n\nFor example:\n\n```swift\nUIApplication.shared.unregisterForRemoteNotifications()\n\nTask {\n\tguard\n\t\tlet deviceID = UIDevice.current.identifierForVendor?.uuidString\n\telse {\n\t\treturn\n\t}\n\n\tawait DevRev.unregisterDevice(deviceID)\n}\n```\n\n#### Handle push notifications\n\nPush notifications coming to the DevRev SDK need to be handled manually. To properly handle them, implement the following method, typically in either the `UNUserNotificationCenterDelegate.userNotificationCenter(_:didReceive:)` or `UIApplicationDelegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:)`:\n\n```swift\nDevRev.processPushNotification(_:)\n```\n\n\u003e [!TIP]\n\u003e For convenience, this method provides two overloads that accept `userInfo` as either `[AnyHashable: Any]` or `[String: any Sendable]` dictionary types.\n\nFor example:\n\n```swift\nfunc userNotificationCenter(\n\t_ center: UNUserNotificationCenter,\n\tdidReceive response: UNNotificationResponse\n) async {\n\tawait DevRev.processPushNotification(response.notification.request.content.userInfo)\n}\n```\n\n## Sample app\n\nA sample app with use cases for both UIKit and SwiftUI has been provided as part of our [public repository](https://github.com/devrev/devrev-sdk-ios).\n\nBefore you start using the sample app you will need to configure it to be used with your Apple Developer team and your DevRev credentials. For your convenience the code has been marked with compiler error directives (`#error`) at the places that need attention.\n\n1. Add your credentials to the relevant `AppDelegate.swift` of the SwiftUI or UIKit sample.\n   - After you have added the credentials, delete or comment out the compiler error lines in the respective files.\n1. Configure the code signing for the sample target:\n\t- Open the project settings (1),\n\t- Select the appropriate target (2),\n\t- Go to the Signing \u0026 Capabilities section (3), and\n\t- Select your development team under Team (4).\n\t\u003cimg src=\"docs/screenshots/screenshot-xcode-signing.png\" width=\"400\" /\u003e\n\n## Troubleshooting\n\n- **Issue**: Can't import the SDK into my app.\n\t**Solution**: Double-check the setup process and ensure that `DevRevSDK` is correctly linked to your application.\n\n- **Issue**: How does the DevRev SDK handle errors?\n\t**Solution**: The DevRev SDK reports all errors in the console using Apple's Unified Logging System. Look for error messages in the subsystem `ai.devrev.sdk`.\n\n- **Issue**: Support chat doesn't show.\n\t**Solution**: Ensure you have correctly called one of the identification methods: `DevRev.identifyUnverifiedUser(...)` or `DevRev.identifyVerifiedUser(...)`.\n\n- **Issue**: Not receiving push notifications.\n\t**Solution**: Ensure that your app is configured to receive push notifications and that your device is registered with the DevRev SDK.\n\n## Migration guide\n\nIf you are migrating from the legacy UserExperior SDK to the new DevRev SDK, please refer to the [Migration guide](./MIGRATION.md) for detailed instructions and feature equivalence.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevrev%2Fdevrev-sdk-ios","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevrev%2Fdevrev-sdk-ios","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevrev%2Fdevrev-sdk-ios/lists"}