# Quick Start

Let's get you started! This guide will walk you through the most important steps

### Install the SDK 🔧

Our iOS SDK is distributed as as a SPM package (Swift Package Manager).  Simply add a SPM dependency in Xcode on `https://github.com/criticalmoments/criticalmoments`.

<details>

<summary>Detailed steps for adding SPM package</summary>

* Open your app project in Xcode. Click "File" > "Add Package Dependencies..."&#x20;
* Paste the following URL in the search box in the top right: `https://github.com/criticalmoments/criticalmoments` and select the Critical Moments package. We suggest leaving the default settings for dependency rules: (Branch=main). We only merge stable releases to our main branch.&#x20;
* Select your iOS app project in the "Add to Project..." dropdown
* Click "Add Package"
* Select your iOS app target in the "Add to Target" dropdown
* Click "Add Package"

</details>

### Create your config file 📄

The CM config file defines how the SDK integrates into your app. Let's get started with a template integration:

* Download our template  `cmDevConfig.json` ([link](https://raw.githubusercontent.com/CriticalMoments/CriticalMoments/refs/heads/vnext/ios/sample_app/SampleApp/demoConfig.json)), which includes a demo of our features on launch. We'll remove the demo later, but it's helpful to test the integration.
* Set the appId on the 3rd line to your app's bundle ID.
* Add the file to your Xcode project.&#x20;

### Integrate the SDK into your app 🧩

Add the following code snippet into your app.

* Put it somewhere that will run right after app startup, such as AppDelegate.didFinishLaunchingWithOptions
* Replace `"cmDevConfig.json"` if you used a different name for the config file.
* The console will show a warning for now, but this will be resolved in a later step of this guide

{% tabs %}
{% tab title="Swift" %}
In your App Delegate imports add:

```swift
import CriticalMoments
```

Add the following code to your app launch. The location depends on the type of app you have:

* &#x20;App Delegate based apps, call from `application(_:didFinishLaunchingWithOptions:)`&#x20;
* SwiftUI lifecycle apps, call from `YourApp.init`

```swift
CriticalMoments.shared().setDevelopmentConfigName("cmDevConfig.json")
// We'll add this later. This must be set before releasing app.
// CriticalMoments.shared().setReleaseConfigUrl("YOUR_URL")
CriticalMoments.shared().start()
```

{% endtab %}

{% tab title="Objective-C" %}
In App Delegate imports section add:

```objectivec
@import CriticalMoments;
```

In App Delegate `application:didFinishLaunchingWithOptions:` add:

```objectivec
[CriticalMoments.shared setDevelopmentConfigName:@"cmDevConfig.json"];
// We will fill this in during a later step. This must be set before releasing to app store
// [CriticalMoments.shared setReleaseConfigUrl:@"YOUR_URL"];
[CriticalMoments.shared start];
```

{% endtab %}
{% endtabs %}

{% hint style="success" %}
Startup work will be dispatched to background threads, and will not impact your app's startup time.
{% endhint %}

### Update Your Info.plist :notebook\_with\_decorative\_cover:

Critical Moments requires a few updates to your Info.plist file. We've made a script to make this easy. Run the following command in your project folder in terminal, and then follow the instructions. It will explain the changes it's making, and won't make any changes until you confim:

{% code overflow="wrap" %}

```sh
bash <(curl -fsSL https://raw.githubusercontent.com/CriticalMoments/CriticalMoments/refs/heads/vnext/ios/tools/setup_tool/setup_cm.sh)
```

{% endcode %}

<details>

<summary>Manual Instructions</summary>

Don't like magic scripts? We get that. You can also update the Info.plist manually.

#### Part 1: Enable Processing For Smart Notifications

Features like [smart notifications](https://docs.criticalmoments.io/notifications/smart-delivery) require running your app to run in the background for brief periods, to check for ideal conditions. To setup background work:

1. In Xcode > project editor > Signing & Capabilities > Add (+) > Background Modes check the boxes for "Background fetch" and "Background processing". See [Apple guide](https://developer.apple.com/documentation/uikit/app_and_environment/scenes/preparing_your_ui_to_run_in_the_background/using_background_tasks_to_update_your_app?language=objc).&#x20;
2. In your `Info.plist` add an array "Permitted background task scheduler identifiers" (`BGTaskSchedulerPermittedIdentifiers`)  with these two values: `io.criticalmoments.bg_fetch` and `io.criticalmoments.bg_process` . See [Apple guide](https://developer.apple.com/documentation/uikit/app_and_environment/scenes/preparing_your_ui_to_run_in_the_background/using_background_tasks_to_update_your_app?language=objc).&#x20;

#### Part 2: Set Bluetooth Reason String

Some optional properties like `has_bt_headphones` and `bluetooth_permission` use the system's bluetooth APIs. These won't be called unless you include them in your config. However Apple will detect them, and want a description in the Info.plist file.

Add an entry for `NSBluetoothAlwaysUsageDescription` to your Info.plist describing your bluetooth usage. If you app uses bluetooth directly, keep the description you have. If you don't otherwise use bluetooth, add a general description, such as "Used to show messages when not using peripherals".&#x20;

</details>

### Test the Integration 🧪

Launch your app. If the integration is working, you should see a CM demo when the app starts; this demo was included in the template file you downloaded earlier.&#x20;

If there are any issues, check the logs. When running a debug build, Critical Moments will log any issues preventing the SDK from working.

{% hint style="info" %}
Note: while CM now works in debug mode, more steps below are needed before releasing to the App Store.&#x20;
{% endhint %}

### Explore the Demo :telescope:

Try out the demo to see each feature of the SDK integrated into your app. To re-lauch the demo, simply restart the app.&#x20;

Once your done with the demo, you can delete the demo content in `cmDevConfig.json`; just be sure leave the `configVersion` and `appId` json entries.

{% hint style="success" %}
**This demo is implemented entirely in config**

It shows how you can add many features to your app without writing code, including fully native UI, integrations into native APIs, powerful conditions, and notifications. If you're curious how any part of the demo works, simply read `cmDevConfig.json`.

In a later step, we'll setup your app to update this config over-the-air, without app updates.
{% endhint %}

### Log important events (optional, recommended) 🎪

The more Critical Moments knows about your user's behaviours, the better you can target and optimize with Critical Moments.&#x20;

We recommend you log important events, including the important actions your users performs in app. See the [events documentation](https://docs.criticalmoments.io/events/event-overview) for the suggested events and details.

{% tabs %}
{% tab title="Swift Example" %}

```swift
CriticalMoments.shared().sendEvent("completed_game_level")
```

{% endtab %}

{% tab title="Objective-C Example" %}

<pre class="language-objectivec"><code class="lang-objectivec"><strong>[CriticalMoments.shared sendEvent:@"completed_game_level"];
</strong></code></pre>

{% endtab %}
{% endtabs %}

### Add custom properties (optional, recommended) 📅

Properties are datapoints used in targeting. The more useful data you add, the more powerful the targeting system can be.

We recommend you add the important properties like account\_creation\_date, has\_subscription, and others. See the [custom properties documentation](https://docs.criticalmoments.io/conditional-targeting/custom-properties) for suggested custom properties, and API reference.

{% tabs %}
{% tab title="Swift Example" %}

```swift
try? CriticalMoments.shared().setIntegerProperty(42, forKey: "max_game_level")
```

{% endtab %}

{% tab title="Objective-C Example" %}

```objectivec
[CriticalMoments.shared registerIntegerProperty:42 
               forKey:@"max_game_level" 
               error:nil];
```

{% endtab %}
{% endtabs %}

### Setup a cloud config file ☁️

For local development you can use your local JSON config file built into the app binary. However, production builds must use a signed config file, hosted on the web.

Read the [Remote Control Docs](https://docs.criticalmoments.io/remote-control-service) for the best practices of picking a hosting provider, signing, and deploying your config.

Once deployed, set the release config URL in your App Delegate, and uncomment the call to `setReleaseConfigUrl("YOUR_URL")`.

You can test your app using the production config by running a "release" build instead of a "debug" build in XCode.

{% hint style="success" %}
**Update Anytime**

Deploying the config file can be done outside of app releases, allowing you to update your apps behaviour without waiting for app reviews, or users to update their builds!
{% endhint %}

### Request Notification Permissions :mailbox\_with\_mail:

If you ever want to show the user notifications, you'll need to ask the user for permission first.

Requesting permission with the Critical Moments helper method instead of the system `requestAuthorization` method is beneficial as it will schedule any CM notifications after approval. An optional callback will be called after the user approves/denies notifications.

{% tabs %}
{% tab title="Swift Example" %}

```swift
CriticalMoments.shared().requestNotificationPermission()
```

{% endtab %}

{% tab title="Objective-C Example" %}

```objectivec
[CriticalMoments.shared
        requestNotificationPermissionWithCompletionHandler:nil];
```

{% endtab %}
{% endtabs %}

### Customize your Integration 🏗️

Remove the demo content from your copy of `cmDevConfig.json` and start building using the powerful combination of conditionals, notifications, events, properties, feature flags, and actions!

Some good places to start and get ideas:

* Download our [**starter template** with 13 features most apps need](https://criticalmoments.io/blog/mobile_app_growth_plan_in_json). Our [blog post](https://criticalmoments.io/blog/mobile_app_growth_plan_in_json) describes how each works, and how to enable them.
* Read our [Concepts Overview](https://docs.criticalmoments.io/concepts-overview) to understand all the tools at your disposal.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.criticalmoments.io/quick-start.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
