> ## Documentation Index
> Fetch the complete documentation index at: https://help.airbridge.io/llms.txt
> Use this file to discover all available pages before exploring further.

# 앱러빈 맥스

<Info>
  **알립니다**

  이 기능은 현재 베타 버전으로 제공되고 있습니다. 서비스 안정화 과정에서 일부 사양이 변경될 수 있습니다.
</Info>

에어브릿지와 앱러빈(AppLovin)의 실시간 인앱 비딩 솔루션 맥스(MAX)를 연동해 광고로 발생한 수익을 에어브릿지 대시보드에서 확인할 수 있습니다. 에어브릿지는 앱러빈 맥스와의 서버 투 서버(S2S) 연동과 SDK 연동을 지원합니다.

<Note>
  **권장하는 연동 방식**

  더 정확한 광고 성과 측정과 활용을 위해 서버 투 서버 연동과 SDK 연동을 모두 설정하는 것을 권장합니다.

  에어브릿지는 SDK 연동으로 실시간으로 받은 데이터를 서버 투 서버 연동으로 받은 보정된 데이터로 자동 업데이트합니다. 또한 SDK 연동으로 받은 데이터는 SKAdNetwork(SKAN)에 활용할 수 있습니다.
</Note>

## 준비하기

에어브릿지 SDK가 아래 버전 이상인지 확인해 주세요. 확인 시점에 에어브릿지 SDK가 아래 버전 미만이라면 서버 투 서버 연동 또는 SDK 연동 중에 1가지만 진행하는 것을 권장합니다.

<Danger>
  **주의하세요**

  서버 투 서버 연동과 SDK 연동을 모두 진행한다면 에어브릿지 SDK가 아래 버전 이상인지 반드시 확인해 주세요.

  충분히 많은 유저가 아래 버전 이상의 SDK가 설치된 앱으로 업데이트한 후에 모든 연동을 진행하는 것을 권장합니다. 아래 버전 미만의 에어브릿지 SDK가 설치된 앱을 사용하는 유저가 대부분일 때 서버 투 서버 연동과 SDK 연동을 모두 진행하면 유저 수가 정확히 집계되지 않습니다.
</Danger>

* Android SDK 2.25.0
* iOS SDK 1.37.3
* React Native SDK 2.8.6
* Flutter SDK 3.5.6
* Cordova SDK 2.6.6
* Expo SDK 2.6.6
* Unity SDK 1.14.5
* Unreal SDK 1.3.5

## SDK 연동하기

아래 링크에 따라 앱러빈 맥스 SDK 를 설치해 주세요.

* [AppLovin MAX의 Android SDK 연동하기](https://developers.applovin.com/en/max/android/overview/integration/)
* [AppLovin MAX의 iOS SDK 연동하기](https://developers.applovin.com/en/max/ios/overview/integration/)
* [AppLovin MAX의 React Native SDK 연동하기](https://developers.applovin.com/en/max/react-native/overview/integration/)
* [AppLovin MAX의 Unity SDK 연동하기](https://developers.applovin.com/en/max/unity/overview/integration)

### 에어브릿지로 광고 수익 데이터 전송하기

앱러빈 맥스에서 발생한 광고 수익 데이터를 에어브릿지로 전송합니다. 앱러빈 맥스 SDK에 광고 수익 데이터 콜백을 설정합니다. 해당 콜백을 활용하여 광고 수익 데이터를 에어브릿지 SDK로 전송합니다.

<AccordionGroup>
  <Accordion title="SDK 연동하기 (Android)">
    #### Android SDK

    <CodeGroup>
      ```kotlin Kotlin lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      override fun onAdRevenuePaid(maxAd: MaxAd) {
          Airbridge.trackEvent(
              AirbridgeCategory.AD_IMPRESSION,
              mapOf(
                  AirbridgeAttribute.ACTION to maxAd.networkName,
                  AirbridgeAttribute.LABEL to maxAd.networkPlacement,
                  AirbridgeAttribute.VALUE to maxAd.revenue,
                  AirbridgeAttribute.AD_PARTNERS to mapOf(
                      "appLovin" to mapOf(
                          "revenue" to maxAd.revenue,
                          "country_code" to AppLovinSdk.getInstance(this).configuration.countryCode,
                          "network_name" to maxAd.networkName,
                          "network_placement" to maxAd.networkPlacement,
                          "adunit_identifier" to maxAd.adUnitId,
                          "creative_identifier" to maxAd.creativeId,
                          "placement" to maxAd.placement,
                          "ad_revenue_format" to maxAd.format.label,
                          "ad_revenue_precision" to maxAd.revenuePrecision
                      )
                  ),
                  // AppLovin MAX has a default currency of USD
                  AirbridgeAttribute.CURRENCY to "USD"
              )
          )
      }
      ```

      ```java Java lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      @Override
      public void onAdRevenuePaid(final MaxAd maxAd) {

          String countryCode = AppLovinSdk.getInstance(this).getConfiguration().getCountryCode();
          String adFormat = maxAd.getFormat().getLabel();
          String precision = maxAd.getRevenuePrecision();

          Airbridge.trackEvent(
                  AirbridgeCategory.AD_IMPRESSION,
                  new HashMap<String, Object>() {{
                      put(AirbridgeAttribute.ACTION, maxAd.getNetworkName());
                      put(AirbridgeAttribute.LABEL, maxAd.getNetworkPlacement());
                      put(AirbridgeAttribute.VALUE, maxAd.getRevenue());
                      put(AirbridgeAttribute.AD_PARTNERS, new HashMap<String, Object>() {{
                          put("appLovin", new HashMap<String, Object>() {{
                              put("revenue", maxAd.getRevenue());
                              put("country_code", countryCode);
                              put("network_name", maxAd.getNetworkName());
                              put("network_placement", maxAd.getNetworkPlacement());
                              put("adunit_identifier", maxAd.getAdUnitId());
                              put("creative_identifier", maxAd.getCreativeId());
                              put("placement", maxAd.getPlacement());
                              put("ad_revenue_format", adFormat);
                              put("ad_revenue_precision", precision);
                          }});
                      }});
                      // AppLovin MAX has a default currency of USD
                      put(AirbridgeAttribute.CURRENCY, "USD");
                  }}
          );
      }
      ```
    </CodeGroup>

    #### Android SDK (Deprecated)

    <CodeGroup>
      ```kotlin Kotlin lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      override fun onAdRevenuePaid(ad: MaxAd) {

          val event = Event("airbridge.adImpression")

          val appLovin = mutableMapOf<String, Any?>()
          appLovin["revenue"] = ad.revenue
          appLovin["country_code"] = AppLovinSdk.getInstance(this).configuration.countryCode
          appLovin["network_name"] = ad.networkName
          appLovin["network_placement"] = ad.networkPlacement
          appLovin["adunit_identifier"] = ad.adUnitId
          appLovin["creative_identifier"] = ad.creativeId
          appLovin["placement"] = ad.placement
          appLovin["ad_revenue_format"] = ad.format.label
          appLovin["ad_revenue_precision"] = ad.revenuePrecision

          val adPartners = mapOf("appLovin" to appLovin)

          event.action = ad.networkName
          event.label = ad.networkPlacement
          event.value = ad.revenue
          event.semanticAttributes = mutableMapOf(
              "adPartners" to adPartners,
              // AppLovin MAX has a default currency of USD
              "currency" to "USD"
          )
          Airbridge.trackEvent(event)
      }
      ```

      ```java Java lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      @Override
      public void onAdRevenuePaid(final MaxAd maxAd)
      {
          Event event = new Event("airbridge.adImpression");
          
          Map<String, Object> appLovin = new HashMap<>();
          appLovin.put("revenue", maxAd.getRevenue());
          appLovin.put("country_code", AppLovinSdk.getInstance(this).getConfiguration().getCountryCode());
          appLovin.put("network_name", maxAd.getNetworkName());
          appLovin.put("network_placement", maxAd.getNetworkPlacement());
          appLovin.put("adunit_identifier", maxAd.getAdUnitId());
          appLovin.put("creative_identifier", maxAd.getCreativeId());
          appLovin.put("placement", maxAd.getPlacement());
          appLovin.put("ad_revenue_format", maxAd.getFormat().getLabel());
          appLovin.put("ad_revenue_precision", maxAd.getRevenuePrecision());

          Map<String, Object> adPartners = new HashMap<>();
          adPartners.put("appLovin", appLovin);

          Map<String, Object> semanticAttributes = new HashMap<>();
          semanticAttributes.put("adPartners", adPartners);
          // AppLovin MAX has a default currency of USD
          semanticAttributes.put("currency", "USD");

          event.setAction(maxAd.getNetworkName());
          event.setLabel(maxAd.getNetworkPlacement());
          event.setValue(maxAd.getRevenue());
          event.setSemanticAttributes(semanticAttributes);
          Airbridge.trackEvent(event);
      }
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="SDK 연동하기 (iOS)">
    #### iOS SDK

    <CodeGroup>
      ```swift Swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      class ExampleViewController : UIViewController {
          func createNativeAdLoader() {
              nativeAdLoader?.revenueDelegate = self;
          }
      }

      extension ExampleViewController: MAAdRevenueDelegate {
          func didPayRevenue(for ad: MAAd) {
              Airbridge.trackEvent(
                  category: AirbridgeCategory.AD_IMPRESSION,
                  semanticAttributes: [
                      AirbridgeAttribute.ACTION: ad.networkName,
                      AirbridgeAttribute.LABEL: ad.networkPlacement,
                      AirbridgeAttribute.VALUE: ad.revenue,
                      AirbridgeAttribute.AD_PARTNERS: [
                          "appLovin": [
                              "revenue": ad.revenue,
                              "country_code": ALSdk.shared().configuration.countryCode,
                              "network_name": ad.networkName,
                              "network_placement": ad.networkPlacement,
                              "adunit_identifier": ad.adUnitIdentifier,
                              "creative_identifier": ad.creativeIdentifier,
                              "placement": ad.placement,
                              "ad_revenue_format": ad.format.label,
                              "ad_revenue_precision": ad.revenuePrecision
                          ]
                      ],
                      AirbridgeAttribute.CURRENCY: "USD"
                  ]
              )
          }
      }
      ```

      ```objective-c Objective-C lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      @implementation ExampleViewController

      - (void)createNativeAdLoader {
          self.nativeAdLoader.revenueDelegate = self;
      }

      - (void)didPayRevenueForAd:(MAAd *)ad {
          [Airbridge trackEventWithCategory:AirbridgeCategory.AD_IMPRESSION semanticAttributes:@{
              AirbridgeAttribute.ACTION: ad.networkName,
              AirbridgeAttribute.LABEL: ad.networkPlacement,
              AirbridgeAttribute.VALUE: @(ad.revenue),
              AirbridgeAttribute.AD_PARTNERS: @{
                  @"appLovin": @{
                      @"revenue": @(ad.revenue),
                      @"country_code": [ALSdk shared].configuration.countryCode,
                      @"network_name": ad.networkName,
                      @"network_placement": ad.networkPlacement,
                      @"adunit_identifier": ad.adUnitIdentifier,
                      @"creative_identifier": ad.creativeIdentifier,
                      @"placement": ad.placement,
                      @"ad_revenue_format": ad.format.label,
                      @"ad_revenue_precision": ad.revenuePrecision
                  }
              },
              AirbridgeAttribute.CURRENCY: @"USD"
          }];
      }
      ```
    </CodeGroup>

    #### iOS SDK (Deprecated)

    <CodeGroup>
      ```swift Swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      class ExampleViewController : UIViewController {
          func createNativeAdLoader() {
              nativeAdLoader?.revenueDelegate = self
          }
      }

      extension ExampleViewController: MAAdRevenueDelegate {
          func didPayRevenue(for ad: MAAd) {
              let event = ABInAppEvent()
              event?.setCategory("airbridge.adImpression")
              event?.setAction(ad.networkName)
              event?.setLabel(ad.networkPlacement)
              event?.setValue(ad.revenue)
              event?.setSemantics([
                  "adPartners": [
                      "appLovin": [
                          "revenue": ad.revenue,
                          "country_code": ALSdk.shared().configuration.countryCode,
                          "network_name": ad.networkName,
                          "network_placement": ad.networkPlacement,
                          "adunit_identifier": ad.adUnitIdentifier,
                          "creative_identifier": ad.creativeIdentifier,
                          "placement": ad.placement,
                          "ad_revenue_format": ad.format.label,
                          "ad_revenue_precision": ad.revenuePrecision
                      ]
                  ],
                  "currency": "USD"
              ])

              event?.send()
          }
      }
      ```

      ```objective-c Objective-C lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      @implementation ExampleViewController

      - (void)createNativeAdLoader {
          self.nativeAdLoader.revenueDelegate = self;
      }

      - (void)didPayRevenueForAd:(MAAd *)ad {
          ABInAppEvent* event = [[ABInAppEvent alloc] init];
          [event setCategory:@"airbridge.adImpression"];
          [event setAction:ad.networkName];
          [event setLabel:ad.networkPlacement];
          [event setValue:ad.revenue];
          [event setSemantics:@{
              @"adPartners": @{
                  @"appLovin": @{
                      @"revenue": @(ad.revenue),
                      @"country_code": [ALSdk shared].configuration.countryCode,
                      @"network_name": ad.networkName,
                      @"network_placement": ad.networkPlacement,
                      @"adunit_identifier": ad.adUnitIdentifier,
                      @"creative_identifier": ad.creativeIdentifier,
                      @"placement": ad.placement,
                      @"ad_revenue_format": ad.format.label,
                      @"ad_revenue_precision": ad.revenuePrecision
                  }
              },
              @"currency": @"USD"
          }];
          [event send];
      }
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="SDK 연동하기 (React Native)">
    #### React Native SDK

    <CodeGroup>
      ```javascript JavaScript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      function App(): JSX.Element {
          useEffect(() => {
              // Helper function to add an ad revenue paid listener
              const addAdRevenuePaidListener = (AdClass) => {
                  AdClass.addAdRevenuePaidListener(adInfo => {
                      if (adInfo) {
                          onAdRevenuePaidEvent(adInfo);
                      }
                  });
              };

              // Set up event listeners
              [BannerAd, InterstitialAd, RewardedAd, AppOpenAd, MRecAd].forEach(addAdRevenuePaidListener);
          }, []);

          const onAdRevenuePaidEvent = (adInfo: AdRevenueInfo) => {
              Airbridge.trackEvent(
                  AirbridgeCategory.AD_IMPRESSION, {
                      [AirbridgeAttribute.ACTION]: adInfo.networkName,
                      [AirbridgeAttribute.LABEL]: adInfo.networkPlacement,
                      [AirbridgeAttribute.VALUE]: adInfo.revenue,
                      [AirbridgeAttribute.AD_PARTNERS]: {
                          'appLovin': {
                              'revenue': adInfo.revenue,
                              'country_code': adInfo.countryCode,
                              'network_name': adInfo.networkName,
                              'network_placement': adInfo.networkPlacement,
                              'adunit_identifier': adInfo.adUnitId,
                              'creative_identifier': adInfo.creativeId,
                              'placement': adInfo.placement,
                              'ad_revenue_format': adInfo.adFormat,
                              'ad_revenue_precision': adInfo.revenuePrecision
                          }
                      },
                      [AirbridgeAttribute.CURRENCY]: 'USD',
                  }
              );
          };

          return ({
              /* Your JSX goes here */
          });
      }
      ```
    </CodeGroup>

    #### React Native SDK (Deprecated)

    <CodeGroup>
      ```javascript JavaScript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      function App(): JSX.Element {
          useEffect(() => {
              // Helper function to add an ad revenue paid listener
              const addAdRevenuePaidListener = (AdClass) => {
                  AdClass.addAdRevenuePaidListener(adInfo => {
                      if (adInfo) {
                          onAdRevenuePaidEvent(adInfo);
                      }
                  });
              };

              // Set up event listeners
              [BannerAd, InterstitialAd, RewardedAd, AppOpenAd, MRecAd].forEach(addAdRevenuePaidListener);
          }, []);

          const onAdRevenuePaidEvent = (adInfo: AdRevenueInfo) => {
              const airbridgeSemanticAttributes = {
                  adPartners: {
                      appLovin: {
                          revenue: adInfo.revenue,
                          country_code: adInfo.countryCode,
                          network_name: adInfo.networkName,
                          network_placement: adInfo.networkPlacement,
                          adunit_identifier: adInfo.adUnitId,
                          creative_identifier: adInfo.creativeId,
                          placement: adInfo.placement,
                          ad_revenue_format: adInfo.adFormat,
                          ad_revenue_precision: adInfo.revenuePrecision
                      },
                  },
                  currency: 'USD', // Assuming USD as default
              }

              Airbridge.trackEvent('airbridge.adImpression', {
                  action: adInfo.networkName,
                  label: adInfo.networkPlacement,
                  value: adInfo.revenue,
                  semanticAttributes: airbridgeSemanticAttributes
              });
          };

          return ({
              /* Your JSX goes here */
          });
      }
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="SDK 연동하기 (Unity)">
    #### Unity SDK

    <CodeGroup>
      ```c# C# lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      private void OnEnable() 
      {
          MaxSdkCallbacks.Banner.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
          MaxSdkCallbacks.Interstitial.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
          MaxSdkCallbacks.Rewarded.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
          MaxSdkCallbacks.RewardedInterstitial.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
          MaxSdkCallbacks.MRec.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
      }

      private void OnAdRevenuePaidEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
      {
          if (adInfo == null) {
              return;
          }

          Airbridge.TrackEvent(
              category: AirbridgeCategory.AD_IMPRESSION,
              semanticAttributes: new Dictionary<string, object>()
              {
                  { AirbridgeAttribute.ACTION, adInfo.NetworkName },
                  { AirbridgeAttribute.LABEL, adInfo.NetworkPlacement },
                  { AirbridgeAttribute.VALUE, adInfo.Revenue },
                  { AirbridgeAttribute.CURRENCY, "USD" },
                  {
                      AirbridgeAttribute.AD_PARTNERS, new Dictionary<string, object>()
                      {
                          {
                              "appLovin", new Dictionary<string, object>()
                              {
                                  { "revenue", adInfo.Revenue },
                                  { "country_code", MaxSdk.GetSdkConfiguration().CountryCode },
                                  { "network_name", adInfo.NetworkName },
                                  { "network_placement", adInfo.NetworkPlacement },
                                  { "adunit_identifier", adInfo.AdUnitIdentifier },
                                  { "creative_identifier", adInfo.CreativeIdentifier },
                                  { "placement", adInfo.Placement },
                                  { "ad_revenue_format", adInfo.AdFormat },
                                  { "ad_revenue_precision", adInfo.RevenuePrecision }
                              }
                          }
                      }
                  },
              }
          );
      }
      ```
    </CodeGroup>

    #### Unity SDK (Deprecated)

    <CodeGroup>
      ```c# C# lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      private void OnEnable()
      {
          MaxSdkCallbacks.Banner.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
          MaxSdkCallbacks.Interstitial.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
          MaxSdkCallbacks.Rewarded.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
          MaxSdkCallbacks.RewardedInterstitial.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
          MaxSdkCallbacks.MRec.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
      }

      private void OnAdRevenuePaidEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
      {
          if (adInfo != null) {
              AirbridgeEvent @event = new AirbridgeEvent("airbridge.adImpression");

              var appLovin = new Dictionary<string, object>();
              appLovin["revenue"] = adInfo.Revenue;
              appLovin["country_code"] = MaxSdk.GetSdkConfiguration().CountryCode;
              appLovin["network_name"] = adInfo.NetworkName;
              appLovin["network_placement"] = adInfo.NetworkPlacement;
              appLovin["adunit_identifier"] = adInfo.AdUnitIdentifier;
              appLovin["creative_identifier"] = adInfo.CreativeIdentifier;
              appLovin["placement"] = adInfo.Placement;
              appLovin["ad_revenue_format"] = adInfo.AdFormat;
              appLovin["ad_revenue_precision"] = adInfo.RevenuePrecision;

              var adPartners = new Dictionary<string, object>();
              adPartners["appLovin"] = appLovin;

              @event.SetAction(adInfo.NetworkName);
              @event.SetLabel(adInfo.NetworkPlacement);
              @event.SetValue(adInfo.Revenue);
              @event.AddSemanticAttribute("adPartners", adPartners);
              // AppLovin MAX has a default currency of USD
              @event.AddSemanticAttribute("currency", "USD");

              AirbridgeUnity.TrackEvent(@event);
          }
      }
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

## 서버 투 서버 연동하기

앱러빈 맥스(AppLovin Max)의 서버 투 서버(S2S) 연동에 앱러빈 맥스의 Report Key가 필요합니다. 앱러빈 맥스에서 확인한 Report Key를 에어브릿지에 입력합니다.

자세한 연동 방법은 아래 가이드를 참고해 주세요.

* [앱러빈 맥스 S2S 연동하기 (유저가이드)](/ko/guides/applovin-max#서버-투-서버-연동하기)

<link rel="alternate" hrefLang="en" href="https://help.airbridge.io/en/developers/applovin-max-ad-revenue-integration" />

<link rel="alternate" hrefLang="ko" href="https://help.airbridge.io/ko/developers/applovin-max-ad-revenue-integration" />
