---
title: "Nhận dữ liệu attribution trong ứng dụng của bạn"
description: "Truy cập dữ liệu attribution chiến dịch trong ứng dụng sau khi Adapty khớp một lượt cài đặt với một chiến dịch."
---

Khi Adapty khớp một lượt cài đặt với một chiến dịch, nó sẽ trả về dữ liệu attribution về ứng dụng của bạn thông qua callback `onInstallationDetailsSuccess`. Sử dụng dữ liệu này để cá nhân hóa trải nghiệm người dùng dựa trên kênh hoặc chiến dịch đã dẫn đến lượt cài đặt.

Dữ liệu attribution được trả về dưới dạng một đối tượng `attribution` lồng nhau bên trong trường `payload`. Nó chứa các trường sau:
| Trường | Mô tả |
|---|---|
| `channel` | Kênh mua người dùng (ví dụ: `facebook`, `tiktok`, `google`, `organic`) |
| `campaign_id` | Mã định danh chiến dịch |
| `campaign_name` | Tên chiến dịch |
| `adset_id` | Mã định danh nhóm quảng cáo / ad group |
| `adset_name` | Tên nhóm quảng cáo / ad group |
| `ad_id` | Mã định danh quảng cáo / creative |
| `ad_name` | Tên quảng cáo / creative |

Tất cả các trường đều là tùy chọn. Đối với các lượt cài đặt organic hoặc khi không thể xác định được attribution, trường `payload` sẽ không bao gồm đối tượng `attribution`.

Để đọc dữ liệu attribution trong ứng dụng của bạn:
<Tabs groupId="current-os" queryString>
<TabItem value="swift" label="Swift" default>

```swift showLineNumbers
Adapty.delegate = self

nonisolated func onInstallationDetailsSuccess(_ details: AdaptyInstallationDetails) {
    guard
        let payloadDict = details.payload?.dictionary,
        let attribution = payloadDict["attribution"] as? [String: Any]
    else { return }

    let channel = attribution["channel"] as? String
    let campaignName = attribution["campaign_name"] as? String
    let adName = attribution["ad_name"] as? String

    print("Channel: \(channel ?? "organic")")
}
```
</TabItem>

<TabItem value="android" label="Kotlin">
```kotlin showLineNumbers
Adapty.setOnInstallationDetailsListener(object : OnInstallationDetailsListener {
    override fun onInstallationDetailsSuccess(details: AdaptyInstallationDetails) {
        val payloadStr = details.payload ?: return
        runCatching {
            val payload = JSONObject(payloadStr)
            val attribution = payload.optJSONObject("attribution") ?: return

            val channel = attribution.optString("channel")
            val campaignName = attribution.optString("campaign_name")
            val adName = attribution.optString("ad_name")

            println("Channel: $channel")
        }.onFailure(Throwable::printStackTrace)
    }
})
```

</TabItem>

<TabItem value="rn" label="React Native">
```typescript showLineNumbers
adapty.addEventListener('onInstallationDetailsSuccess', details => {
    try {
        if (!details.payload) return;
        const payload = JSON.parse(details.payload);
        const attribution = payload.attribution;
        if (!attribution) return;

        const channel = attribution.channel;
        const campaignName = attribution.campaign_name;
        const adName = attribution.ad_name;

        console.log('Channel:', channel ?? 'organic');
    } catch (error) {
        console.error('Error parsing payload:', error);
    }
});
```

</TabItem>
<TabItem value="flutter" label="Flutter">
```dart showLineNumbers
Adapty().onUpdateInstallationDetailsSuccessStream.listen((details) {
  final payloadStr = details.payload;
  if (payloadStr == null) return;

  final payload = json.decode(payloadStr) as Map<String, dynamic>;
  final attribution = payload['attribution'] as Map<String, dynamic>?;
  if (attribution == null) return;

  final channel = attribution['channel'] as String?;
  final campaignName = attribution['campaign_name'] as String?;
  final adName = attribution['ad_name'] as String?;

  print('Channel: ${channel ?? 'organic'}');
});
```

</TabItem>

</Tabs>