# Reading Consent from an airgap.js WebView (/docs/consent-management/mobile-consent/reading-consent-from-an-airgap-js-webview)

### Introduction [#introduction]

When your mobile app embeds a WebView that loads a page with airgap.js running, consent choices the user makes in the browser context can be retrieved by calling [`airgap.getConsent()`](../reference/airgap/api.mdx#airgapgetconsent-trackingconsentdetails). This guide walks through extracting that consent and forwarding it to the Transcend native SDK so your app-side tracking respects the same preferences.

The overall flow has four steps:

1\. Establish a JavaScript bridge between your native app and the WebView.

2\. Retrieve consent by calling `airgap.getConsent()` from within the WebView's JavaScript context, and sent the consent's purposes object back across the bridge to native code.

3\. Call `setConsent` on the Transcend SDK with the purposes map.

### Prerequisites [#prerequisites]

- Your app already loads a WebView whose page includes the airgap.js script.
- The Transcend SDK is initialized in your native app via TranscendAPI.init().

#### 1. Set Up a JavaScript Bridge [#1-set-up-a-javascript-bridge]

If your app does not already have a JavaScript-to-native bridge, add one. The bridge gives JavaScript running inside the WebView a way to send data back to your native code.

#### 2. Read and pass WebView consent through the bridge [#2-read-and-pass-webview-consent-through-the-bridge]

First, you'll need to ensure that your getConsent code runs after airgap has finished initializing; this is accomplished by attaching a callback to [`airgap.ready`](../reference/airgap/api.mdx#airgapready).

If your bridge code already interacts with airgap.js in some way, then it likely already waits for the airgap ready signal, otherwise you will need to wrap your `getConsent` call within the ready callback, as shown below:

```javascript
airgap.ready(() => {
  const purposes = airgap.getConsent().purposes;
  const purposesString = JSON.stringify(purposes);
  window.ConsentBridge.receiveConsent(purposesString);
});

```

Either way, you will need to make your bridge code invoke `airgap.getConsent()` and pass the stringified purposes object back through to the native context.

#### 3. Call setConsent with the purposes [#3-call-setconsent-with-the-purposes]

When the bridge callback fires, deserialize the JSON string into a `<String, Boolean>` map and call the SDK's `setConsent` method with it.

```kotlin
private fun handlePurposes(purposesJson: String) {
    try {
        val gson = Gson()
        val type = object : TypeToken<Map<String, Boolean>>() {}.type
        val purposes: Map<String, Boolean> = gson.fromJson(purposesJson, type)

        val success = TranscendAPI.setConsent(purposes)
        if (success) {
            Log.d("Consent", "Consent synced from WebView")
        } else {
            Log.e("Consent", "Failed to set consent")
        }
    } catch (e: Exception) {
        Log.e("Consent", "Failed to sync consent from Webview", e)
    }
}
```

```swift
private func handlePurposes(_ purposesJson: String) {
    guard let data = purposesJson.data(using: .utf8) else {
        NSLog("[Consent] Failed to sync consent from WebView: invalid data")
        return
    }
    do {
        guard let purposes = try JSONSerialization.jsonObject(with: data) as? [String: Bool] else {
            NSLog("[Consent] Failed to sync consent from WebView: invalid JSON structure")
            return
        }
        let success = TranscendAPI.setConsent(purposes)
        if success {
            NSLog("[Consent] Consent synced from WebView")
        } else {
            NSLog("[Consent] Failed to set consent")
        }
    } catch {
        NSLog("[Consent] Failed to sync consent from WebView: %@", error.localizedDescription)
    }
}
```
