# App Store

{% stepper %}
{% step %}

#### [SDK Integration](#sdk-integration-1)

{% endstep %}

{% step %}

#### [Settings on the App Store Connect side](#settings-on-app-store-connect-side)

{% endstep %}

{% step %}

#### [Settings on devtodev side](#settings-on-devtodev-side-1)

[For In-App Purchases](#in-app-purchases)&#x20;

[For Subscriptions](#subcriptions)&#x20;
{% endstep %}
{% endstepper %}

## SDK integration

{% hint style="info" %}
**Prerequisites:**

**Native SDK**

* StoreKit SDK v1
* DTDAnalytics SDK **2.5.0** and higher

**Unity**

* DTDAnalytics **3.9.0** and higher
* [DTDPurchases](https://github.com/devtodev-analytics/package_Purchases/releases) **3.9.0** and higher

Check [Initialization](#initialization) when moving to Unity IAP 5.0.4 and higher!&#x20;
{% endhint %}

### Initialization

To initialize the service, call the `startAutoTracking` method of the `DTDPurchases` interface. Call the method after the SDK initialization call.&#x20;

See examples below:

{% tabs fullWidth="false" %}
{% tab title="Swift" %}

```swift
let config = DTDAnalyticsConfiguration()
DTDAnalytics.initialize(applicationKey: "App ID", configuration: config)
DTDPurchases.startAutoTracking()
```

{% endtab %}

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

```objectivec
DTDAnalyticsConfiguration *config;
[DTDAnalytics applicationKey:@"App ID" configuration:config];
[DTDPurchases startAutoTracking];
```

{% endtab %}

{% tab title="Unity" %}
**For Unity IAP below 5.0**

```csharp
DTDAnalytics.Initialize("App ID", new DTDAnalyticsConfiguration
{
  UserId = userId,
  ApplicationVersion = Application.version,
  CurrentLevel = lvl,
  LogLevel = DTDLogLevel.No,
  TrackingAvailability = DTDTrackingStatus.Enable
});
DTDPurchases.StartAutoTracking();
```

***

**For Unity IAP 5.0.4 and higher (5.1 and higher recommended)**

Add `StoreKitSelector.forceStoreKit1 = true;` before IAP initialization:

```csharp
    public async Task InitializePurchasing()
    {
        StoreKitSelector.forceStoreKit1 = true;
        storeController = UnityIAPServices.StoreController();
        // UnityIAPServices initialization
        await storeController.Connect();
    }
```

After that, initialize devtodev SDK&#x20;

```csharp
DTDAnalytics.Initialize("App ID", new DTDAnalyticsConfiguration
{
  UserId = userId,
  ApplicationVersion = Application.version,
  CurrentLevel = lvl,
  LogLevel = DTDLogLevel.No,
  TrackingAvailability = DTDTrackingStatus.Enable
});
DTDPurchases.StartAutoTracking();
```

{% endtab %}
{% endtabs %}

### **Subscription restore**

Subscription renewals, cancellations, and other status changes are tracked using server-to-server data from the App Store. See the following sections for setup.&#x20;

In order to be able to track status changes for subscriptions that were issued prior to the devtodev SDK integration, you must send the history of previously purchased user subscriptions to devtodev.&#x20;

The SDK keeps track of the need to send this historical data so that it does not make “unnecessary” requests to the App Store. Use the `isRestoreTransactionHistoryRequired` method to check whether it is necessary to send data about previously purchased subscriptions to devtodev.&#x20;

The `isRestoreTransactionHistoryRequired` method returns a `BOOL` value.&#x20;

Here is an example of a purchase history request with the check:

{% tabs fullWidth="false" %}
{% tab title="Swift" %}

```swift
DTDAnalytics.isRestoreTransactionHistoryRequired { isNeedRestore in
  if isNeedRestore {
    DispatchQueue.main.async {
      SKPaymentQueue.default().restoreCompletedTransactions()
    }
  }
}
```

{% endtab %}

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

```objectivec
[DTDAnalytics isRestoreTransactionHistoryRequiredWithCompletionHandler:^(BOOL isNeedRestore){
  if (isNeedRestore == true) {
    dispatch_async(dispatch_get_main_queue(), ^{
      [SKPaymentQueue.defaultQueue restoreCompletedTransactions];
    });
  }
}];
```

{% endtab %}

{% tab title="Unity" %}
{% code fullWidth="true" %}

```csharp
if (Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.OSXPlayer)
{
  var apple = storeExtensionProvider.GetExtension<IAppleExtensions>();
  DTDAnalytics.IsRestoreTransactionHistoryRequired((required) =>
  {
    if(!required) return;
    apple.RestoreTransactions((success, text) =>
    {
      Debug.Log(success ? $"Purchases restored successfully on iOS." : $"{text}");
    });
  });
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="info" %}
`DTDPurchases` service will get the information about previously purchased subscriptions automatically from `SKPaymentQueue`. Sending the data via the [`subscriptionHistory`](/integration/integration-of-sdk-v2/setting-up-events/basic-methods.md#subscriptions) method is not required.&#x20;
{% endhint %}

## **Settings on the App Store Connect side** <a href="#settings-on-app-store-connect-side" id="settings-on-app-store-connect-side"></a>

To get detailed information about the transaction, devtodev requires access to the App Store Server API. To grant this access, you will need to generate an **In-App Purchase API key**.

Generating the key:

1. Authorize on [App Store Connect](https://appstoreconnect.apple.com/).
2. Navigate to the Users and Access section.

   <figure><img src="/files/nlCW7KobBAoN8OCGEUjt" alt=""><figcaption></figcaption></figure>
3. In the **Integrations** tab (1), select **In-App Purchase** from the menu on the left (2), and click `(+)` to add the key (3).

   <figure><img src="/files/U5wjgYYJkkc5R7k0rZHj" alt=""><figcaption></figcaption></figure>
4. Specify the name of the key, for example: "devtodev API Key", and click `Generate`.

   <figure><img src="/files/5KfKfAQLlIezTSkpzYwF" alt=""><figcaption></figcaption></figure>
5. To grant the necessary access to the devtodev service, it is necessary to pass  the following information:

   * Issuer ID
   * Key ID
   * The generated **.p8** file of the In-App Purchase key&#x20;
   * Bundle identifier of the application (App Bundle ID)

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

## **Settings on devtodev side** <a href="#settings-on-devtodev-side" id="settings-on-devtodev-side"></a>

### In-App Purchases

1. Go to **Settings → Payments integration → IAP auto tracking → Integrate**.<br>

   <figure><img src="/files/eeOumjr6wxoCxHnvpNbj" alt=""><figcaption></figcaption></figure>
2. Fill in the integration form with the data [obtained earlier from the App Store](#settings-on-app-store-connect-side):&#x20;

   * App Bundle ID
   * Issuer ID
   * Key ID
   * Upload the **.p8** file of the In-App Purchase key.

   <figure><img src="/files/PM8oCESR9qShxGsyZwG4" alt=""><figcaption></figcaption></figure>
3. When the integration is complete, the status will change to **Active**. <br>

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

### Subcriptions

1. In order for IAP auto tracking to work correctly with subscriptions, you need to integrate App Store Server Notification. Go to **Settings → Payments integration → Subscriptions → Integrate**. <br>

   <figure><img src="/files/SNCTCUQvdbjrXT0qPtpt" alt=""><figcaption></figcaption></figure>
2. Fill in the iOS Bundle ID and copy the **Endpoint URL**.<br>

   <figure><img src="/files/Jj0lirFa3KqD3S9TL6N0" alt=""><figcaption></figcaption></figure>
3. Navigate to [App Store Connect](https://appstoreconnect.apple.com/). In the left menu column, under **General**, go to **App information**. Paste the copied endpoint URL into the **Production Server UR**L and **Sandbox Server URL** fields. \
   Click `Save` to confirm your changes.

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


---

# 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.devtodev.com/integration/autocapture/automatic-payment-tracking/app-store.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.
