# Track Metrics The SideKit SDK provides multiple ways to send analytics signals. This data powers your dashboard charts and allows you to build targeted version gates based on user behavior. Make sure you've configured the SDK with your API key before sending any signals to ensure they are tracked correctly. ## Add Your Custom Signal in the Dashboard Signals UI Navigate to the `Settings` page for your app and add your signal in the `Custom Signals` section. Here `purchases` is a custom signal we've chosen to track for this app. This whitelists the signal name and SideKit will accept data for this signal. ## Sending Signals :::ios You can track events in your app using three primary methods, depending on how much detail you need. ::: ### 1. Simple Key The simplest way to send a signal is with just a key string. This is perfect for binary events (like "session\_start"). :::ios ```swift SideKit.shared.sendSignal("user_login") ``` ::: ### 2. Key-Value Pairs Send a signal with both a key and a value. SideKit automatically generates pie charts in your dashboard for the distribution of these values. :::ios ```swift SideKit.shared.sendSignal(key: "purchase_amount", value: "99.99") ``` ::: :::ios ### 3. Signal Objects For more complex scenarios, you can use the `SideKit.Signal` struct. This is especially useful when building arrays of signals. ```swift SideKit.shared.sendSignal( SideKit.Signal(name: "button_click", value: "checkout") ) ``` ::: *** ## Bulk Tracking If you have multiple events that happen simultaneously, you can batch them into a single call: :::ios ```swift let signals = [ SideKit.Signal(name: "page_view", value: "home"), SideKit.Signal(name: "interaction", value: "header_clicked") ] SideKit.shared.sendSignal(signals) ``` ::: ## Best Practices
Batch when possible : If sending multiple signals in a loop, batch them into an array to reduce network requests. Use descriptive keys : Choose clear, consistent names (e.g., onboarding_step_1 ) to keep your dashboard organized. Analytics state : SideKit respects the user's analytics preference. If analytics is disabled, signals will be silently ignored.
# Add an App
Select Add new app from the app switcher in the top left of the dashboard.
Enter your app's name as well as an App Store and/or Play Store URL if your app is currently live. If your app is already live on the App Store, SideKit will automatically pull your app icon from your store URL. If it's not live yet, don't worry—you can always update the icon URL later.
## What's a Signal? A signal is an analytics metric that you'd like to track with SideKit. Any time the event you'd like to track takes place in your app you can [record it with the SideKit SDK](../analytics/track-a-signal). ### Default Signals SideKit automatically records three essential signals out-of-the-box so you can start seeing data immediately: We keep default signals to a minimum, you get to decide what you want to track. # Configure SideKit ## Add SideKit to your Project :::ios To add the SideKit iOS SDK to your Xcode project, follow these steps:
In Xcode, go to File \> Add Package Dependencies...
In the search bar, enter the GitHub URL:
``` https://github.com/appsidekit/ios-sdk ```
Select the ios-sdk package from the results
Configure the dependency rule:
  • Set Dependency Rule to "Up to Next Major Version"
  • This will use versions 1.0.0 up to (but not including) 2.0.0
Click Add Package to complete the installation.
Ensure SideKit appears in your project settings under General \> Frameworks, Libraries, and Embedded Content .
::: ## Configure SideKit in your app :::ios In your `ContentView`, add the configuration in a `.task` modifier with your [API key](/ios/helpers/find-api-key): ```swift .task { await SideKit.shared.configure( apiKey: "YOUR-API-KEY", verbose: true // Optional: enables detailed logs ) } ``` In your `AppDelegate` or `SceneDelegate`, call configure in `application(_:didFinishLaunchingWithOptions:)` or `scene(_:willConnectTo:options:)`: ```swift Task { await SideKit.shared.configure( apiKey: "YOUR-API-KEY", verbose: true // Optional: enables detailed logs ) } ``` ::: Set verbose = true during development to see all SideKit logs in your console. This is helpful for verifying that your signals are being tracked successfully. The SideKit SDK will now be available in your app, and you can start sending signals! # Find Your API Key Your API key is a unique identifier used to authenticate your app's requests to SideKit. ## Locating your API Key
Navigate to your app in the SideKit dashboard.
Select Settings from the sidebar navigation menu.
Scroll down to the Danger Zone section to find your key.
## Rotating Your API Key If your API key is compromised, you can generate a new one by clicking the **Rotate** button. Rotating your API key is irreversible. Once rotated:
  • Older app versions using the old key will stop sending signals.
  • Version gates will no longer be enforced on those versions.
  • You must release an update with the new key immediately.
# Find Your Bundle ID :::ios A **Bundle ID** (Bundle Identifier) is a unique identifier that represents your app on the App Store. They typically follow a reverse-DNS format, such as `com.yourcompany.appname`. Read more [here](https://developer.apple.com/documentation/appstoreconnectapi/bundle-ids). ## Locating the Bundle ID in Xcode You can find your Bundle ID in your project settings.
Open your project in Xcode and select the project file at the top of the Project Navigator .
Select your app target under the Targets list.
Go to the General tab and look for the Identity section.
::: Bundle IDs are case-sensitive! Double-check for any accidental capital letters or spaces. # Track Metrics The SideKit SDK provides multiple ways to send analytics signals. This data powers your dashboard charts and allows you to build targeted version gates based on user behavior. Make sure you've configured the SDK with your API key before sending any signals to ensure they are tracked correctly. ## Add Your Custom Signal in the Dashboard Signals UI Navigate to the `Settings` page for your app and add your signal in the `Custom Signals` section. Here `purchases` is a custom signal we've chosen to track for this app. This whitelists the signal name and SideKit will accept data for this signal. ## Sending Signals :::react-native You can track events in your app using two primary methods, depending on how much detail you need. ::: ### 1. Simple Key The simplest way to send a signal is with just a key string. This is perfect for binary events (like "session\_start"). :::react-native ```ts const { sendSignal } = useSideKit(); sendSignal("user_login") ``` ::: ### 2. Key-Value Pairs Send a signal with both a key and a value. SideKit automatically generates pie charts in your dashboard for the distribution of these values. :::react-native ```ts sendSignal("purchase_amount", "99.99") ``` ::: *** ## Bulk Tracking If you have multiple events that happen simultaneously, you can batch them into a single call: :::react-native ```ts const { sendSignals } = useSideKit(); sendSignals([ { key: "page_view", value: "home" }, { key: "interaction", value: "header_clicked" } ]) ``` ::: ## Best Practices
Batch when possible : If sending multiple signals in a loop, batch them into an array to reduce network requests. Use descriptive keys : Choose clear, consistent names (e.g., onboarding_step_1 ) to keep your dashboard organized. Analytics state : SideKit respects the user's analytics preference. If analytics is disabled, signals will be silently ignored.
# Add an App
Select Add new app from the app switcher in the top left of the dashboard.
Enter your app's name as well as an App Store and/or Play Store URL if your app is currently live. If your app is already live on the App Store, SideKit will automatically pull your app icon from your store URL. If it's not live yet, don't worry—you can always update the icon URL later.
## What's a Signal? A signal is an analytics metric that you'd like to track with SideKit. Any time the event you'd like to track takes place in your app you can [record it with the SideKit SDK](../analytics/track-a-signal). ### Default Signals SideKit automatically records three essential signals out-of-the-box so you can start seeing data immediately: We keep default signals to a minimum, you get to decide what you want to track. # Configure SideKit ## Add SideKit to your Project :::react-native To add the SideKit React Native SDK to your project, just install the NPM package: ```sh npm install @sidekit/react-native @react-native-async-storage/async-storage # or yarn add @sidekit/react-native @react-native-async-storage/async-storage ``` ::: ## Configure SideKit in your app :::react-native To initialize SideKit, wrap your app's contents with `SideKitProvider`: ```ts import { SideKitProvider } from '@sidekit/react-native'; function App() { return ( ); } ``` ::: Set verbose = true during development to see all SideKit logs in your console. This is helpful for verifying that your signals are being tracked successfully. The SideKit SDK will now be available in your app, and you can start sending signals! # Find Your API Key Your API key is a unique identifier used to authenticate your app's requests to SideKit. ## Locating your API Key
Navigate to your app in the SideKit dashboard.
Select Settings from the sidebar navigation menu.
Scroll down to the Danger Zone section to find your key.
## Rotating Your API Key If your API key is compromised, you can generate a new one by clicking the **Rotate** button. Rotating your API key is irreversible. Once rotated:
  • Older app versions using the old key will stop sending signals.
  • Version gates will no longer be enforced on those versions.
  • You must release an update with the new key immediately.
# Find Your Bundle ID :::react-native A **Bundle ID** (Bundle Identifier) is a unique identifier that represents your app on the App Store/Play Store. They typically follow a reverse-DNS format, such as `com.yourcompany.appname`. Read more [here](https://developer.apple.com/documentation/appstoreconnectapi/bundle-ids). ## Locating the Bundle ID in your Expo Project You can find your Bundle IDs for both iOS and Android in your app's `app.json` file: ```json { "expo": { ... "ios": { "bundleIdentifier": "com.sidekit.example" }, "android": { "package": "com.sidekit.example" }, ... } } ``` ::: Bundle IDs are case-sensitive! Double-check for any accidental capital letters or spaces. # Block an App Version ## In the Dashboard Manage Versions UI Navigate to `Versions` in the Dashboard under your app. SideKit will use analytics data to automatically infer the most popular app versions from the last 7 days. Tap configure to add an app version to SideKit's tracking. On an existing version you can set the status as forced or dismissible to block the version. Forced gates require users to update their app to proceed whereas dismissible gates can be skipped. ## In Your App ### Automatic ✨

Zero Code Required

SideKit automatically presents a beautiful version gate when users need to update. No setup, no code, no maintenance required.
Latest version pulled from App Store automatically "What's New" text synced from your App Store submission Works out-of-the-box with zero configuration
### Custom View for Blocked App Versions For custom version gates, see [Showing Custom Version Gates](./showing-custom-version-gates). # Set a Minimum Version ## In the Dashboard Manage Versions UI Navigate to `Versions` in the Dashboard under your app, set `MIN` from the dropdown to set an app version as a floor. Users on that app version or above will be able to access the app and any users below it will be shown a forced version gate which will require them to update their app to proceed. ## In Your App ### Automatic ✨

Zero Code Required

SideKit automatically presents a beautiful version gate when users need to update. No setup, no code, no maintenance required.
Latest version pulled from App Store automatically "What's New" text synced from your App Store submission Works out-of-the-box with zero configuration
Version gates triggered by minimum version requirements are never dismissible. Users must update to continue using the app. The "Skip for now" button only appears in dismissible version gates. ### Custom View for Blocked App Versions For custom version gates, see [Showing Custom Version Gates](./showing-custom-version-gates). # Showing Custom Version Gates ## Setup :::react-native To use custom version gates, configure SideKit with `presentationMode: "manual"`: ```ts import { SideKitProvider } from '@sidekit/react-native'; function App() { return ( ); } ``` ::: When using manual presentation mode, you're responsible for displaying the version gate UI. SideKit will still fetch and manage version requirements, but won't automatically show the update screen. ## GateInformation Struct Use the `GateInformation` struct to access version gate data and build your custom UI: :::react-native ```ts class GateInformation { gateType: VersionGateType; lastGateUpdate: string; latestVersion: string | null; whatsNew: string | null; storeUrl: string | null; } ``` ::: :::react-native ::: ## Gate Types The `VersionGateType` enum defines version gate behavior: :::react-native ```ts enum VersionGateType { Live = -1, Forced = 0, Dismissible = 1, } ``` ::: ### Understanding Gate Types
Live
The user's app version is not blocked by a version gate. You should not show an update screen in this case.
Forced
User must update to continue. The gate cannot be dismissed. Used for critical updates or minimum version enforcement.
Dismissible
User can dismiss the gate and continue using the app. Your custom view should include a close/skip button.
If the gate type is dismissible, your custom view must include UI to close or skip the update. Failing to do so will trap users in the update screen. ## Displaying Your Custom Gate :::react-native ```ts const { showUpdateScreen, gateInformation } = useSideKit(); {showUpdateScreen && gateInformation && ( {/* Show your custom update UI */} )} ``` ::: :::react-native Access gateInformation to get the current gate data, including version requirements, release notes, and App Store/Play Store URL. ::: # Block an App Version ## In the Dashboard Manage Versions UI Navigate to `Versions` in the Dashboard under your app. SideKit will use analytics data to automatically infer the most popular app versions from the last 7 days. Tap configure to add an app version to SideKit's tracking. On an existing version you can set the status as forced or dismissible to block the version. Forced gates require users to update their app to proceed whereas dismissible gates can be skipped. ## In Your App ### Automatic ✨

Zero Code Required

SideKit automatically presents a beautiful version gate when users need to update. No setup, no code, no maintenance required.
Latest version pulled from App Store automatically "What's New" text synced from your App Store submission Works out-of-the-box with zero configuration
### Custom View for Blocked App Versions For custom version gates, see [Showing Custom Version Gates](./showing-custom-version-gates). # Set a Minimum Version ## In the Dashboard Manage Versions UI Navigate to `Versions` in the Dashboard under your app, set `MIN` from the dropdown to set an app version as a floor. Users on that app version or above will be able to access the app and any users below it will be shown a forced version gate which will require them to update their app to proceed. ## In Your App ### Automatic ✨

Zero Code Required

SideKit automatically presents a beautiful version gate when users need to update. No setup, no code, no maintenance required.
Latest version pulled from App Store automatically "What's New" text synced from your App Store submission Works out-of-the-box with zero configuration
Version gates triggered by minimum version requirements are never dismissible. Users must update to continue using the app. The "Skip for now" button only appears in dismissible version gates. ### Custom View for Blocked App Versions For custom version gates, see [Showing Custom Version Gates](./showing-custom-version-gates). # Showing Custom Version Gates ## Setup :::ios To use custom version gates, configure SideKit with `presentationMode: .manual`: ```swift SideKit.shared.configure(apiKey: "YOUR-API-KEY", presentationMode: .manual) ``` ::: When using manual presentation mode, you're responsible for displaying the version gate UI. SideKit will still fetch and manage version requirements, but won't automatically show the update screen. ## GateInformation Struct Use the `GateInformation` struct to access version gate data and build your custom UI: :::ios ```swift struct GateInformation { let gateType: VersionGateType let lastGateUpdate: String let latestVersion: String? let whatsNew: String? let storeURL: String? } ``` ::: :::ios ::: ## Gate Types The `VersionGateType` enum defines version gate behavior: :::ios ```swift enum VersionGateType: Int, Codable { case live = -1 case forced = 0 case dismissible = 1 } ``` ::: ### Understanding Gate Types
Live
The user's app version is not blocked by a version gate. You should not show an update screen in this case.
Forced
User must update to continue. The gate cannot be dismissed. Used for critical updates or minimum version enforcement.
Dismissible
User can dismiss the gate and continue using the app. Your custom view should include a close/skip button.
If the gate type is dismissible, your custom view must include UI to close or skip the update. Failing to do so will trap users in the update screen. ## Displaying Your Custom Gate :::ios Bind your custom gate view to `SideKit.shared.showUpdateScreen` to control when it appears: ```swift struct ContentView: View { var body: some View { YourAppContent() .fullScreenCover(isPresented: SideKit.shared.$showUpdateScreen) { if let gateInfo = SideKit.shared.gateInformation { CustomVersionGateView(gateInfo: gateInfo) } } } } ``` ```swift class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Observe showUpdateScreen changes SideKit.shared.$showUpdateScreen .sink { [weak self] shouldShow in if shouldShow, let gateInfo = SideKit.shared.gateInformation { self?.presentCustomGate(gateInfo) } } .store(in: &cancellables) } func presentCustomGate(_ gateInfo: GateInformation) { let gateVC = CustomVersionGateViewController(gateInfo: gateInfo) gateVC.modalPresentationStyle = .fullScreen present(gateVC, animated: true) } } ``` ::: :::ios Access SideKit.shared.gateInformation to get the current gate data, including version requirements, release notes, and App Store URL. This data is automatically synced from your App Store listing. :::