<br />

Custom events enable publishers using Ad Manager
mediation to add waterfall mediation for a third-party ad network that isn't one
of the [supported ad networks](https://developers.google.com/ad-manager/mobile-ads-sdk/unity/choose-networks.md.txt).
This guide explains how to use an existing custom event built for Android and
iOS in a Unity project.

## Prerequisites

Before you continue, do the following:

- [Set up Google Mobile Ads Unity Plugin](https://developers.google.com/ad-manager/mobile-ads-sdk/unity/quick-start.md.txt). Your Unity
  app should already have the Google Mobile Ads Unity plug-in imported.

- Custom event adapters already built for Android and iOS. To create custom
  event adapters, refer to our custom events guides on
  [Android](https://developers.google.com/ad-manager/mobile-ads-sdk/android/custom-events/setup.md.txt) and
  [iOS](https://developers.google.com/ad-manager/mobile-ads-sdk/ios/custom-events/setup.md.txt).

## Define a custom event

In order for a custom event to participate in mediation, the custom event must
be defined in the Ad Manager web interface. [Add a
custom event](https://support.google.com/admanager/answer/7390828) to both of your
Android and iOS mediation groups.

| How to fill out parameters ||
|---|---|
| Class Name (iOS) | For iOS, enter the name of the class that implements the custom event. If your class is implemented in Swift, you need to prefix the class name with the name of its app / framework module (for example, `appName.className`). Target name is required if you have multiple targets in your project or if the project name is different from the target name. With the target name, it would look like this: `appName_targetName.className`. In addition, remember to replace any non-alphanumeric characters such as dashes with underscores. |
| Class Name (Android) | For Android, make sure the value you give for the `Class Name` is the fully qualified class name for Android (for example `com.google.ads.mediation.sample.customevent.SampleCustomEvent`). |
| Label | Enter a unique name for the event. |
| Parameter | If you wish to pass a string argument to your custom event, for example an ad unit ID. |

## Import custom event libraries

Custom events might require additional libraries to be included to work
properly. For example, you might need to include the following libraries:

- Android third-party SDK
- Android third-party custom event
- iOS third-party ad SDK
- iOS third-party custom event

### Types of libraries

There are multiple ways to import Android or iOS code into a Unity project,
including:

- Importing prebuilt Android or iOS artifacts using the External Dependency Manager for Unity
- Importing AAR plug-ins and Android libraries
- Importing Java and Kotlin source files
- Importing iOS source files and static libraries

Depending on how the libraries you use are packaged, you might need a different
import strategy for each library. Each option is discussed in more detail later.

### (Recommended) Import prebuilt Android or iOS artifacts

Import prebuilt artifacts from Maven or CocoaPods using the [External
Dependency Manager for Unity](https://github.com/googlesamples/unity-jar-resolver).
This plug-in is included with the GoogleMobileAds plug-in.

To import existing artifacts, create a configuration file to define your
imports. The filename and path have the following requirements:

- The file must exist in the `/Editor/` folder.
- The filename must end with `Dependencies.xml`.

For example, to import custom event's adapters for a hypothetical ad network
named `AdPub`, create the file:

    Assets/AdPub/Editor/AdPubDependencies.xml

Next, define your dependencies inside the `AdPubDependencies.xml` file. Rules
for configuring the imports can be found at
[External Dependency Manager for Unity Getting
Started](https://github.com/googlesamples/unity-jar-resolver#getting-started). The
following code snippet includes the Android and iOS SDK and custom event
libraries for a hypothetical "AdPub" ad network.

#### `Assets/AdPub/Editor/AdPubDependencies.xml`

```xml
<dependencies>
  <androidPackages>
    <androidPackage spec="com.adpub.android:adpub-sdk:1.0.0" />
    <androidPackage spec="com.adpub.android:adpub-custom-event:1.0.0">
      <repositories>
        <repository>https://repo.maven.apache.org/maven2/</repository>
        <repository>https://dl.google.com/dl/android/maven2/</repository>
      </repositories>
    </androidPackage>
  </androidPackages>
  <iosPods>
    <iosPod name="AdPubSDK" version="1.0" />
    <iosPod name="AdPubCustomEvent" version="1.0">
      <sources>
        <source>https://github.com/CocoaPods/Specs</source>
      </sources>
    </iosPod>
  </iosPods>
</dependencies>
```

If your custom event artifact already has a dependency on the required ad
network SDK, you don't need to define the SDK dependency explicitly:
[Example](https://github.com/googleads/googleads-mobile-unity/blob/main/mediation/Meta/source/plugin/Assets/GoogleMobileAds/Mediation/MetaAudienceNetwork/Editor/MetaAudienceNetworkMediationDependencies.xml)

The External Dependency Manager automatically monitors for configuration changes
and resolves dependencies. You can also execute manual resolution with the
following menu command:

    Assets > External Dependency Manager > Android Resolver > Force Resolve

### Import AAR plug-ins and Android libraries

Unity supports importing `*.aar` files as well as Android library projects. If
your Android custom event is packaged this way, see [AAR plug-ins and Android
Libraries](https://docs.unity3d.com/Manual/AndroidAARPlugins.html) for instructions on
how to include those files in your Unity project.

### Import Java and Kotlin source files

Starting in Unity 2018.2 or higher, if your Android custom event code comprises
of uncompiled `*.java` or `*.kt` files, you can use [Java or Kotlin source files
as plug-ins](https://docs.unity3d.com/Manual/AndroidJavaSourcePlugins.html).

### Import iOS source files and static libraries

Unity supports `*.framework` artifacts, `*.h`, and `*.m` source files. Importing
iOS artifacts and source files is explained in [Unity's guide for native
plug-ins](https://docs.unity3d.com/Manual/PluginsForIOS.html).

## Test custom events with ad inspector

[Ad inspector](https://developers.google.com/ad-manager/mobile-ads-sdk/unity/ad-inspector.md.txt) can be used to test
that custom events have been imported correctly into your application. Ad
inspector can be open with just gestures or programmatically with minimal code.

## (Optional) Call third-party SDK native methods from C# scripts

Third-party ad network SDKs could have special requirements which require
calling Android or iOS methods directly. The process for calling these methods
directly are as follows:

1. Define a common interface for platform clients
2. Implement a default client for unsupported platforms
3. Implement an Android client for calling Android methods
4. Implement an iOS client for calling iOS methods
5. Implement a [client
   factory](https://en.wikipedia.org/wiki/Factory_method_pattern#C#) to conditionally switch between iOS and Android clients
6. Define an API for accessing all third-party ad network SDK functionalities

The following section shows how these steps are implemented for a hypothetical
ad network called "AdPub" in a C# API that can call into the methods on Android
and iOS:

### Android

```java
package com.adpub.android;

public class AdPubSdk
{
    public static void setHasUserConsent(boolean hasUserConsent);
}
```

### iOS

```objective-c
@interface AdPubSdk : NSObject
+ (void)setHasUserConsent:(BOOL)hasUserConsent;
@end
```

### Define a common interface for platform clients

Create an `IAdPubClient` interface with a method that represents the underlying
Android and iOS API.

#### `Assets/AdPub/Common/IAdPubClient.cs`

```c#
namespace AdPub.Common
{
    public interface IAdPubClient
    {
        ///<summary>
        /// Sets a flag indicating if the app has user consent for advertisement.
        ///</summary>
        void SetHasUserConsent(bool hasUserConsent);
    }
}
```

### Define a default client for unsupported platforms

Create a `DefaultClient` class implementing the `IAdPubClient` interface that
just logs the method name. Use this implementation for the Unity editor and all
platforms other than Android or iOS.

#### `Assets/AdPub/Common/DefaultClient.cs`

```c#
namespace AdPub.Common
{
    public class DefaultClient : IAdPubClient
    {
        public void SetHasUserConsent(bool hasUserConsent)
        {
            Debug.Log("SetHasUserConsent was called.");
        }
    }
}
```

### Implement an iOS platform client

Create an `iOSAdPubClient` class implementing the `IAdPubClient` interface on
iOS. This implementation uses
[InteropServices](https://docs.unity3d.com/Manual/PluginsForIOS.html) to call
the `setHasUserConsent()` method in the iOS `AdPubSdk` class.

#### `Assets/AdPub/Platforms/iOS/iOSAdPubClient.cs`

```c#
// Wrap this class in a conditional operator to make sure it only runs on iOS.
#if UNITY_IOS

// Reference InteropServices to include the DLLImportAttribute type.
using System.Runtime.InteropServices;

using AdPub.Common;

namespace AdPub.Platforms.Android
{
    public class iOSAdPubClient : IAdPubClient
    {
        public void SetHasUserConsent(bool hasUserConsent)
        {
            GADUAdPubSetHasUserConsent(hasUserConsent);
        }

        [DllImport("__Internal")]
        internal static extern void GADUAdPubSetHasUserConsent(bool hasUserConsent);
    }
}
#endif
```

Next, implement the `GADUAdPubSetHasUserConsent()` method that was defined
above. Create `AdPubClientBridge.m` with a `C` method
`GADUAdPubSetHasUserConsent()` to handle the method call from Unity, and invoke
the `AdPubSDK`.

`AdPubClientBridge` is an iOS source file and must be placed inside the
`Plugins/iOS` folder as explained in [Unity's guide for native
plug-ins](https://docs.unity3d.com/Manual/PluginsForIOS.html).

#### `Assets/AdPub/Plugins/iOS/AdPubClientBridge.m`

```c#
#import <AdPubSDK/AdPubSDK.h>

void GADUAdPubSetHasUserConsent(BOOL hasUserConsent) {
  [AdPubSDK setHasUserConsent:hasUserConsent];
}
```

### Implement an Android platform client

Create an `AndroidAdPubCient` class implementing the `IAdPubClient` interface on
Android. This implementation uses the[Android Java helper
classes](https://docs.unity3d.com/2017.4/Documentation/Manual/AndroidJARPlugins.html)
to call the Android static method `setHasUserConsent()`.

As the Android Java helper classes are only available during the Android
runtime, you can prevent compilation errors using the `UNITY_ANDROID` [compiler
directive](https://docs.unity3d.com/Manual/PlatformDependentCompilation.html) to wrap
the class as shown in the code snippet. Alternatively, you can use [Assembly
definitions](https://docs.unity3d.com/Manual/ScriptCompilationAssemblyDefinitionFiles.html)
on Unity 2017.4 and later to resolve this issue.

#### `Assets/AdPub/Platforms/Android/AndroidAdPubClient.cs`

```c#
// Wrap this class in a conditional operator to make sure it only runs on Android.
#if UNITY_ANDROID

// Reference the UnityEngine namespace which contains the JNI Helper classes.
using UnityEngine;

using AdPub.Common;

namespace AdPub.Platforms.Android
{
    public class AndroidAdPubClient : IAdPubClient
    {
        public void SetHasUserConsent(bool hasUserConsent)
        {
             // Make a reference to the com.adpub.AdPubSDK.
            AndroidJavaClass adPubSdk = new AndroidJavaClass("com.adpub.AdPubSdk");

            // Call the native setHasUserConsent method of com.adpub.AdPubSDK.
            adPubSdk.CallStatic("setHasUserConsent", hasUserConsent);
        }
    }
}
#endif
```

### Create a factory method to return the correct client implementation

Now that you have implementations of the client for every platform, create an
`AdPubClientFactory` class to return the correct implementation of the
`IAdPubClient` interface depending on the runtime platform. This class uses
[compiler
directives](https://docs.unity3d.com/Manual/PlatformDependentCompilation.html) to
return the correct `IAdPubClient`client.

#### `Assets/AdPub/Common/AdPubClientFactory.cs`

```c#
namespace AdPub.Common
{
    public class AdPubClientFactory
    {
        // Return the correct platform client.
        public static IAdPubClient GetClient()
        {
#if   !UNITY_EDITOR && UNITY_ANDROID
            return new AdPub.Platforms.Android.AndroidAdPubClient();
#elif !UNITY_EDITOR && UNITY_IOS
            return new AdPub.Platforms.iOS.iOSAdPubClient();
#else
            // Returned for the Unity Editor and unsupported platforms.
            return new DefaultClient();
#endif
        }
    }
}
```

### Define a public API for each interface method

Create an `AdPubApi` class that has method calls for each client method in your
`IAdPubClient` interface. This class uses the `AdPubClientFactory` to get an
instance of the `IAdPubClient` and calls that client for the underlying SDK
functionalities.

#### `Assets/AdPub/AdPubApi.cs`

```c#
using AdPub.Common;

namespace AdPub
{
    public class AdPubApi
    {
        private static readonly IAdPubClient client = GetAdPubClient();

        // Returns the correct client for the current runtime platform.
        private static IAdPubClient GetAdPubClient()
        {
            return AdPubClientFactory.GetClient();
        }

        // Sets the user consent using the underlying SDK functionality.
        public static void SetHasUserConsent(bool hasUserConsent)
        {
            client.SetHasUserConsent(hasUserConsent);
        }
    }
}
```

### Call your newly defined API

Here is how you can call the API defined above:

#### `Assets/Scripts/AdPubController.cs`

```c#
using UnityEngine;
using AdPub;

public class AdPubController : MonoBehaviour
{
    // TODO: Get consent from the user and update this userConsent field.
    public bool userConsent;

    // Called on startup of the GameObject it's assigned to.
    public void Start()
    {
        // Pass the user consent to AdPub.
        AdPubApi.SetHasUserConsent(userConsent);
    }
}
```

### Additional third-party ad network adapter examples

Visit the [Google Mobile Ads Unity plug-in Github
repository](https://github.com/googleads/googleads-mobile-unity/tree/main/mediation)
for additional examples of third-party mediation adapters implementing C# APIs
to wrap calls to iOS and Android methods.