# Cordova

## Things to keep handy before starting your integration with Apxor

Please have the following handy before beginning the integration:

* **Application identifier** generated on the Apxor dashboard for your app\
  \
  ([Read more on how to fetch the application identifier from Apxor dashboard](/getting-started-with-apxor/adding-a-new-app.md))
* **App Bundle Id :** Every app has a unique application ID that looks like `com.example.myapp`. This id uniquely identifies the app on the device and also on the app store.\
  \
  [(Know more about bundle ids here)](https://developer.android.com/studio/build/configure-app-module)
* **The list of events** to setup triggers and track goals, user properties that allows to personalize messages and to target better.\
  \
  ([Read more on how you can setup here](/getting-started-with-apxor/api-guides/cordova.md))

## Cordova Integration

### Step 1: Getting started

Run the following command in your terminal from the project folder. This command will fetch the apxor plugins for you.

```bash
cordova plugin add cordova-plugin-apxor-sdk
```

### Step 2: Handle deeplink redirection

Use `registerDeeplinkHandler` to listen on deeplink redirection from Apxor SDK and handle redirection logic (including external redirection) within application logic as follows

```dart
ApxorSDK.registerDeeplinkHandler((deeplinkUrl) => {
  // Whenever redirection happens from InApp notification buttons,
  // this callback will be executed.

  switch (deeplinkUrl) {
    case "scheme://about":
      // Redirect to About Component
      break;
    default:
      // Check if it's external URL and redirect to Browser
      break;
    // and so on
  }
});
```

## Android Integration

### Step 1: Add dependencies

Add plugin dependencies to your application `build.gradle` file

**`Path: <project>/<app-module>/build.gradle`**:

[Check the latest release notes here.](/getting-started-with-apxor/release-notes.md#android)

#### 1.1 ApxorSDK dependencies (mandatory)

```groovy
dependencies {
//...

    // Event tracking and a must-have dependency for other plugins
    implementation 'com.apxor.androidx:apxor-android-sdk-core:3.2.5@aar'


    // Add these for Realtime Actions and Surveys
    implementation 'com.apxor.androidx:apxor-android-sdk-qe:1.8.9@aar'
    implementation 'com.apxor.androidx:apxor-android-sdk-rtm:2.7.5@aar'
    implementation 'com.apxor.androidx:surveys:2.3.0@aar'


    // Helper plugin to create walkthroughs
    implementation 'com.apxor.androidx:wysiwyg:1.6.5@aar'
    
    // Add the below two dependencies to establish an SSE connection for WYSIWYG
    implementation 'com.squareup.okhttp3:okhttp:4.9.0'
    implementation 'com.launchdarkly:okhttp-eventsource:2.5.0'
    
//...
}
```

#### 1.2 Add exoplayer in your app (optional)

<details>

<summary>Add exoplayer in your app</summary>

Exoplayer enables you to configure Picture In Picture videos from the Apxor dashboard; if you are already using the exoplayer in your app, this step is not needed; otherwise, add the following dependency in the application  `build.gradle` file. To use video pip templates, this is necessary.

<img src="/files/BMQoL6soL1X6E8GmUgTs" alt="" data-size="original">

<mark style="background-color:blue;">**For com.apxor.androidx:apxor-android-sdk-rtm:2.3.6\@aar version onwards**</mark>

```gradle
dependencies {
  //... 

  implementation 'androidx.media3:media3-exoplayer:1.1.1'
  implementation 'androidx.media3:media3-ui:1.1.1'


  //...
  }
```

<mark style="background-color:blue;">**For com.apxor.androidx:apxor-android-sdk-rtm:2.3.5\@aar and below**</mark>

```gradle
dependencies {
  //... 

  implementation 'com.google.android.exoplayer:exoplayer:2.14.0'

  //...
  }
```

</details>

### Step 2: Add Proguard Rules <a href="#android-integration" id="android-integration"></a>

{% hint style="info" %}
**Note**

If you use proguard to obfuscate the classes, you have to add the following to ignore obfuscation for Apxor SDK classes
{% endhint %}

Configure the below rules in your `proguard-rules.pro` file

**`Path: <project>/<app-module>/gradle.properties`**:

```java
-keep class com.apxor.** { *; }
-dontwarn com.apxor.**
```

{% hint style="info" %}

**Note:**

If you use `androidx` libraries, add the following property in `gradle.properties` file

```properties
android.enableJetifier = true
```

{% endhint %}

### Step 2: Initialize Apxor Android SDK <a href="#initialize-apxor-android-sdk" id="initialize-apxor-android-sdk"></a>

* To **Auto initialize** SDK (Recommended), add following `meta-data` tag inside your `application` tag in your `AndroidManifest.xml` file

  ```xml
  <application>
      <!-- You must replace your app in android:value attribute -->
      <meta-data android:name="APXOR_APP_ID" android:value="APP_ID" />
  </application>
  ```
* To manually initialize SDK, call `ApxorSDK.initialize` method in your `Application` class

  ```java
  //...
  import com.apxor.androidsdk.core.ApxorSDK;

  public class MyApplication extends Application {
      @Override
      public void onCreate() {
          // ...
          ApxorSDK.initialize(<YOUR_APP_ID>, this.getApplicationContext());
      }
  }
  ```

{% hint style="info" %}
Click here to [Add New App](/getting-started-with-apxor/adding-a-new-app.md) and [how to get the app id](/getting-started-with-apxor/adding-a-new-app.md#step-5-copy-the-application-identifier)
{% endhint %}

### Step 3: Enable uninstall tracking for your users \[Optional] <a href="#to-track-uninstalls" id="to-track-uninstalls"></a>

{% hint style="info" %}
**Note**

* If you would like to track uninstalls, you must include `apxor-android-sdk-push` dependency in `app/build.gradle` file and corresponding JSON object in `assets/plugins.json` file
* Apxor sends silent push notifications to track uninstalls. Please make sure you handle push notifications which will be sent with your SENDER\_ID and ignore all notifications other than your SENDER\_ID
  {% endhint %}

Apxor uses your firebase server key to send silent push notifications to track uninstalls in order to measure outcomes of your campaign. To enable this please do the following :

**Path : `app/build.gradle`**

<details>

<summary><em><strong><code>firebase-messaging</code></strong><strong> </strong><strong>version >=</strong><strong> </strong><strong><code>22.0.0</code></strong></em></summary>

* Add the following dependency in your `app/build.gradle`

  ```groovy
  dependencies {
    // Add this to track uninstalls and send push notifications from Apxor dashboard
    implementation('com.apxor.androidx:apxor-android-sdk-push-v2:1.2.7@aar') {
      exclude group: 'com.google.firebase'
    }
  }
  ```
* Add the following in `plugins.json` file

  ```json
  {
    "plugins": [
      {
        "name": "push",
        "class": "com.apxor.androidsdk.plugins.push.v2.PushPlugin"
      }
    ]
  }
  ```

</details>

<details>

<summary><em><strong><code>firebase-messaging</code></strong><strong> </strong><strong>version</strong><strong> </strong><strong><code>&#x3C; 22.0.0</code></strong></em></summary>

* Add the following dependency in your `app/build.gradle`

  ```groovy
  dependencies {
    // Add this to track uninstalls and send push notifications from Apxor dashboard
    implementation('com.apxor.androidx:apxor-android-sdk-push:1.2.7@aar') {
      exclude group: 'com.google.firebase'
    }
  }
  ```
* If you are not using `FirebaseMessagingService`, you can skip this step. Otherwise, add the following

  ```java
  public class MyFirebaseMessagingService extends FirebaseMessagingService {
      @Override
      public void onMessageReceived(RemoteMessage remoteMessage) {
          // Creating Notification Channel
          ApxorPushAPI.createNotificationChannel(this.getApplicationContext(), "Apxor", "Apxor", "Apxor");
          if (remoteMessage.getFrom().equals(YOUR_FCM_SENDER_ID)) {
              // Push Notification receiver with your Sender Id
          } else {
              // Check if Push Notification received from Apxor
              if (ApxorPushAPI.isApxorNotification(remoteMessage)) {
                  ApxorPushAPI.handleNotification(remoteMessage, getApplicationContext());
              } else {
                  // Silent or Data push notification which you can send through Apxor dashboard
              }
          }
      }
  }
  ```
* Add the following in `plugins.json` file

  ```json
  {
    "plugins": [
      {
        "name": "push",
        "class": "com.apxor.androidsdk.plugins.push.PushPlugin"
      }
    ]
  }
  ```

[Read here](/getting-started-with-apxor/firebase-credentials-optional.md) on how to get your firebase sender ID and also FCM server key to share it with apxor to configure uninstall tracking.

</details>

### Step 4: To view tooltips, Coachmark and Badges <a href="#to-view-tooltips" id="to-view-tooltips"></a>

{% hint style="info" %}
**Note**

To anchor a tooltip or coachmark or badge to any UI element, this step is mandatory.

If you will only use In-app messages, this step can be skipped.
{% endhint %}

In your `MainActivity` `onCreate` method you must set the tag for the `WebView` as follows to view the tooltips.

```java
public class MainActivity extends CordovaActivity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        // Your logic goes here

        appView.getView().setTag("MyWebView");
    }
}
```

### Step 5: Ensuring ApxorSDK is initialised successfully <a href="#ensuring-apxorsdk-is-initialised-successfully" id="ensuring-apxorsdk-is-initialised-successfully"></a>

We have to verify for two things as follows :

**SDK Initialisation**

On running your android project lookout for the following log in logcat :

```java
ApxorSDK(v3**) successfully initialized for: APP_ID
```

<figure><img src="/files/7hLMlroJFuHWhmh7schm" alt=""><figcaption></figcaption></figure>

**Plugin Initialisation**

By default, only error logs are enabled. To see debug logs for plugin initialisation and to confirm tracking event triggers, user properties. Please run the below command in terminal

```java
adb shell setprop log.tag.Apxor VERBOSE
```

<figure><img src="/files/sRoXlvsMhggAWYRwLrnC" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
**Note**

Apxor uploads data only when the app is minimized to the background. If you are running from Android Studio (emulators or devices), do not stop the app, just press on the "home" button in order for data to be uploaded.
{% endhint %}

### Step 6: Log data to set up triggers and measure goals

Now as we are done with basic integration, we can go ahead to setup event triggers, capture data for targeting and to personalize messaging.

[Please follow the guide here](/getting-started-with-apxor/api-guides/cordova.md) to log user properties, events and event properties.

## iOS integration <a href="#ios-integration" id="ios-integration"></a>

### Initialize Apxor iOS SDK <a href="#initialize-apxor-ios-sdk" id="initialize-apxor-ios-sdk"></a>

* To **Auto initialize** SDK, add the following inside your `application` plist file.
* Open your application's **Info.plist** as source code.

  <figure><img src="https://docs.apxor.com/docs/assets/SDKs/open_as_source_code.png" alt=""><figcaption></figcaption></figure>
* Copy paste the below piece of code, to create an entry for ApxorSDK.

```xml
  <key>Apxor</key>
  <dict>
      <key>Core</key>
      <string>{YOUR_APP_ID}</string>
      <key>APXSurveyPlugin</key>
      <true/>
      <key>APXRTAPlugin</key>
      <true/>
      <key>APXWYSIWYGPlugin</key>
      <true/>
  </dict>
```

### Configuring Test Device

* First, you need to configure your app to ensure there is a URL Scheme with your application's bundle identifier as the value.
* If your app already has a URL Scheme with your application's bundle identifier as the value, you can skip this step.

### Configuring URL Scheme

* To configure URL scheme, goto your project settings, select **`Targets`**. Click on the **`Info`** tab.
* Select the **`URL Types`**, and click on the **`+`** button to add a new URL Scheme.
* Add a new URL Scheme with your **`bundle identifier`** as the value.
* Your bundle identifer will be in the format, **`com.xxxx.xxxx`**
* Use the image below for reference.

<figure><img src="/files/h0DXDpIUwnWJcE5UUtIf" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
**Note**

Make sure the URL scheme has the value of your **bundle identifier** that was provided in the dashboard while registering with us. Also, the app must have same **bundle identifier.**
{% endhint %}

### Handling the deep link

<details>

<summary>Using AppDelegate</summary>

* You'd need to enable Apxor to handle Apxor specific deeplinks.
* In your application's **`AppDelegate`** file, in the function **`application(_:open:options:)`**, add the following code at the beginning,

```swift
// ObjC
NSString *urlStr = url.absoluteString;
if ([urlStr containsString:@"add-test-device"]) {
  [ApxorSDK handleDeeplink:url];
}
```

```objectivec
// Swift
/*
  Apxor's code to handle deeplinks
  */
let urlStr = url.absoluteString
if (urlStr.contains("add-test-device")) {
    ApxorSDK.handleDeeplink(url)
}
```

* This will ensure the Apxor specific deep links are handle by our SDK.

</details>

<details>

<summary>Using SceneDelegate</summary>

* You'd need to enable Apxor to handle Apxor specific deeplinks.
* In your application's **`SceneDelegate`** file, add the following code at the beginning,

```objectivec
// ObjC
- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts {
  for(UIOpenURLContext *x in URLContexts) {
    NSURL *url = x.URL;
    if([[url absoluteString] containsString:@"add-test-device"])
    {
      [ApxorSDK handleDeeplink:url];
    }
    break;
  }
}
```

```swift
// Swift
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
  let url = URLContexts.first?.url
  let urlStr = url?.absoluteString
  if (urlStr!.contains("add-test-device")) {
    ApxorSDK.handleDeeplink(url!)
  }
}
```

</details>

### To show tooltips <a href="#to-show-tooltips" id="to-show-tooltips"></a>

* In your `MainViewController` (the ViewController extending the `CDVViewController`) `init` method you must set the tag for the `WebView` as follows to view the tooltips.

```objc
  // ...
  if (self.webView != null) {
    [self.webView setTag:123];
    NSLog(@"My webview is: %@", self.webView);
  } else {
    NSLog(@"Error in setting TAG to webview");
  }
  // ...
```

{% hint style="info" %}
**Note**

Ensure your webview isn't null and the TAG is set correctly.
{% endhint %}

* You have to init the APXWKScriptHandler and call registerEventsAndScripts method to make sure any the calls made in the webview are taken care by the native SDK. It's as follows,

  * If you don't already have a bridging header, [checkout how to create a bridging header.](https://developer.apple.com/documentation/swift/importing-objective-c-into-swift)
  * Add the following in the bridging header file.

  ```dart
  #import "APXRTAPlugin/APXWKScriptHandler.h"
  ```

  * Now, add the following to the init method of your webview

  ```dart
  let apxHandler: APXWKScriptHandler = APXWKScriptHandler.init(handlerFor: webView)
  apxHandler.registerEventsAndScripts()
  ```
* Here's how to do the same thing in objective-C.

  * Make sure there's a proper WKUserContentController set to your WkWebView, if not please init it and use that config to initialise your WKWebView.

  ```dart
  #import "APXRTAPlugin/APXWKScriptHandler.h"
  ```

  ```ObjectiveC
  ...
  // add apxor's script handler
  APXWKScriptHandler *scriptHandler = [[APXWKScriptHandler alloc] initWithHandlerForWebView:_webView];
  [scriptHandler registerEventsAndScripts];
  ```

### Ensuring ApxoriOSSDK is initialised successfully <a href="#ensuring-apxoriossdk-is-initialised-successfully" id="ensuring-apxoriossdk-is-initialised-successfully"></a>

* Lookout for the following log in `console output`,

  ```
   ApxoriOSSDK (2XX) : initialized!
  ```

{% hint style="info" %}
**Note**

Apxor uploads data only when the app is minimized to the background. If you are running from XCode (emulators or devices), do not stop the app, just press on the "home" button in order for data to be uploaded.
{% endhint %}

### Additional features API Guide <a href="#api-guide" id="api-guide"></a>

[Click here for guides](/getting-started-with-apxor/api-guides/cordova.md) to log user properties, events and event properties.


---

# 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://guides.apxor.com/getting-started-with-apxor/sdk/cordova.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.
