Select platform: [Android](https://developers.google.com/interactive-media-ads/docs/sdks/android/client-side/secure-signals-developer.md.txt "View this page for the Android platform docs.") [iOS](https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/secure-signals-developer.md.txt "View this page for the iOS platform docs.")

<br />

Secure signals are encoded data a client device collects and shares with select
bidders. This page guides you on collecting and sending secure signals to
Google Ad Manager using the Interactive Media Ads (IMA) SDK.

## Before you begin

Before continuing, verify you have the
IMA SDK for Android v3.29.0 or higher.

## Create the secure signal adapter interface

To collect and provide secure signals, create classes that implement the
interface:

> [!NOTE]
> **Note:** The IMA SDK loads your adapter class using reflection. To prevent removal of minified code at build time, add the Android annotation [`@Keep`](https://developer.android.com/reference/androidx/annotation/Keep) to your class.

```java
package companydomain.path.to.securesignals;
import android.content.Context;
import androidx.annotation.Keep;
import com.google.ads.interactivemedia.v3.api.signals.SecureSignalsAdapter;

/**
 * An example implementation of Secure Signals adapter.
 */
@Keep
public final class MySecureSignalsAdapter implements SecureSignalsAdapter {
  /**
   * Default constructor with no arguments for IMA SDK to instantiate this class.
   */
  public MySecureSignalsAdapter() {
  }
}
```

## Initialize the adapter

The IMA SDK initializes each adapter once by calling the initialization method
of the adapter. Implement this method to begin any encryption dependencies, set
up caches, or pre-calculating any signals that remain the same in all signal
collection calls.

The following example initializes the adapter:

```java
  ...
  /**
   * Initialize your SDK and any dependencies.
   * IMA SDK calls this function exactly once before signal collection.
   *
   * @param context  The activity context that creates an ads loader.
   * @param callback A callback function to pass initialization results to IMA SDK.
   */
  @Override
  public void initialize(Context context, SecureSignalsInitializeCallback callback) {
    // Initialize your SDK and any dependencies.
    ...

    // Notify IMA SDK of initialization success.
    callback.onSuccess();

    // If signal collection fails, call callback.onFailure();
    // callback.onFailure(new Exception("Signal collection failed."));
  }
  ...
```

## Signal collection

Before an ad request initiates, the IMA SDK calls a collect signals method
asynchronously. These signal collector methods contain a callback function to
pass the encrypted signals or report an error.

> [!NOTE]
> **Note:** Within 500 milliseconds, you must complete the signal collection, encryption, and pass the encrypted signal to the callback function. After 500 milliseconds, the IMA SDK discards any signal collection.

The following examples collect the secure signals through the callback
function:

```java
  ...
  /**
   * Invokes your SDK to collect, encrypt and pass the signal collection results to IMA SDK.
   * IMA SDK calls this function before each ad request.
   *
   * @param context  The activity context that creates an ads loader.
   * @param callback A callback function to pass signal collection results to IMA SDK.
   */
  @Override
  public void collectSignals(Context context, SecureSignalsCollectSignalsCallback callback) {

    try {
      // Collect and encrypt the signals.
      String signals = ...;

      // Pass the encrypted signals to IMA SDK.
      callback.onSuccess(signals);
    } catch (Exception e) {
      // Pass signal collection failures to IMA SDK.
      callback.onFailure(e);
    }
  }
  ...
```

## Report errors

To communicate with users who use your adapter class, report all errors during
the signal collection and pass them to the signal collector callback. This
process troubleshoots issues that occur during integration of your adapter to
applications.

Errors that might appear are as follows:

- Your SDK or a dependency is not found in the application.
- Your SDK or a dependency doesn't have the required permission or user consent to work.

### Specify the adapter version

In your workflow, verify you specify the version of the adapter. The IMA SDK
includes your adapter version in each ad request and passes them with the secure
signals in a bid request.

In the bid request, based on the adapter version, you can identify the
encryption, encoding, and formatting details the adapter uses to create the
secure signals.

The following example specifies the adapter version:

```java
  ...
  /**
   * Specifies this adapter's version.
   */
  private static final VersionInfo AdapterVersion = new VersionInfo(1, 0, 1);
  ...
  /**
   * @return The version of this adapter.
   *         IMA SDK calls this function before each ad request.
   */
  @Override
  public VersionInfo getVersion() {
    return AdapterVersion;
  }
  ...
```

## Return the SDK runtime version

You can design your adapter to work with multiple versions of your SDK. For the
adapter to work with multiple versions, verify you return the runtime version of
the SDK. In each ad request, the IMA SDK includes the runtime version with the
adapter version.

The following examples requests and returns the SDK runtime version:

```java
  ...
  /**
   * @return The version of your SDK that this adapter is depending on.
   *         IMA SDK calls this function before each ad request.
   */
  @Override
  public VersionInfo getSDKVersion() {
    // Request the version from your SDK and convert to an IMAVersion.
    int[] mySDKVersion = ...;

    return new VersionInfo(mySDKVersion[0], mySDKVersion[1], mySDKVersion[2]);
  }
  ...
```

## Register the adapter with Google

For Google to authorize the adapter for signal collection, you must register
the Android package name or
with Google.
The IMA SDK initializes only those adapters you register with Google.

## Validate the adapter

To validate the adapter, complete the following sections:

### Configure the test application

Before you validate the adapter, configure the test application. Complete the
following steps:

1. Add the dependencies for IMA SDK to the app-level Gradle file of your
   module, such as `app/build.gradle`:

       dependencies {
         implementation 'com.google.ads.interactivemedia.v3:interactivemedia:3.29.0'
       }

2. [Add build dependencies](https://developers.google.com/interactive-media-ads/docs/sdks/android/client-side/developer.android.com/build/dependencies) such as
   your adapter and SDK.

### Verify the signals

To verify that your adapter sends signals, use a network proxy to monitor ad
request traffic of your application. If successful, you see the signals in each
ad request.

## Review the complete examples

This section captures the completed example of all steps and available for your
reference.

```java
package companydomain.path.to.securesignals;
import android.content.Context;
import androidx.annotation.Keep;
import com.google.ads.interactivemedia.v3.api.VersionInfo;
import com.google.ads.interactivemedia.v3.api.signals.SecureSignalsAdapter;
import com.google.ads.interactivemedia.v3.api.signals.SecureSignalsCollectSignalsCallback;
import com.google.ads.interactivemedia.v3.api.signals.SecureSignalsInitializeCallback;

/**
 * An example implementation of Secure Signals adapter.
 */
@Keep
public final class MySecureSignalsAdapter implements SecureSignalsAdapter {
  /**
   * Specifies this adapter's version.
   */
  private static final VersionInfo AdapterVersion = new VersionInfo(1, 0, 1);
  /**
   * Default constructor with no arguments for IMA SDK to instantiate this class.
   */
  public MySecureSignalsAdapter() {
  }
  /**
   * Initialize your SDK and any dependencies.
   * IMA SDK calls this function exactly once before signal collection.
   *
   * @param context  The activity context that creates an ads loader.
   * @param callback A callback function to pass initialization results to IMA SDK.
   */
  @Override
  public void initialize(Context context, SecureSignalsInitializeCallback callback) {
    try {
      // Initialize your SDK and any dependencies.
      ...

      // Notify IMA SDK of initialization success.
      callback.onSuccess();
    } catch (Exception e) {
      // Pass initialization failures to IMA SDK.
      callback.onFailure(e);
    }
  }
  /**
   * Invokes your SDK to collect, encrypt and send the signal collection results to IMA SDK.
   * IMA SDK calls this function before each ad request.
   *
   * @param context  The activity context that creates an ads loader.
   * @param callback A callback function to pass signal collection results to IMA SDK.
   */
  @Override
  public void collectSignals(Context context, SecureSignalsCollectSignalsCallback callback) {
    try {
      // Collect and encrypt the signals.
      String signals = ...;

      // Pass the encrypted signals to IMA SDK.
      callback.onSuccess(signals);
    } catch (Exception e) {
      // Pass signal collection failures to IMA SDK.
      callback.onFailure(e);
    }
  }
  /**
   * @return The version of this adapter.
   * IMA SDK calls this function before each ad request.
   */
  @Override
  public VersionInfo getVersion() {
    return AdapterVersion;
  }
  /**
   * @return The version of your SDK that this adapter is depending on.
   * IMA SDK calls this function before each ad request.
   */
  @Override
  public VersionInfo getSDKVersion() {
    // Request the version from your SDK and convert to an IMAVersion.
    int[] mySDKVersion = ...;
    return new VersionInfo(mySDKVersion[0], mySDKVersion[1], mySDKVersion[2]);
  }
}
```