# Before send

Copy as Markdown[Open in ChatGPT](https://chatgpt.com/?q=Read%20https%3A%2F%2Fcoralogix.com%2Fdocs%2Fuser-guides%2Frum%2Fsdk-installation%2Fapple%2Fios%2Fconfiguration%2Fbefore-send.md%20and%20help%20me%20with%20my%20question%20about%20this%20Coralogix%20documentation%20page.)[Open in Claude](https://claude.ai/new?q=Read%20https%3A%2F%2Fcoralogix.com%2Fdocs%2Fuser-guides%2Frum%2Fsdk-installation%2Fapple%2Fios%2Fconfiguration%2Fbefore-send.md%20and%20help%20me%20with%20my%20question%20about%20this%20Coralogix%20documentation%20page.)

### Before send[​](#before-send "Direct link to Before send")

Enable event access and modification before sending to Coralogix, supporting content modification.

```
let options = CoralogixExporterOptions(coralogixDomain: CORALOGIX-DOMAIN,

                                        environment: "ENVIRONMENT",

                                        application: "APP-NAME",

                                        version: "APP-VERSION",

                                        publicKey: "API-KEY",

                                        beforeSend: { cxRum in

            var editableCxRum = cxRum

            if var sessionContext = editableCxRum["session_context"] as? [String: Any] {

                sessionContext["user_email"] = "john.doe@coralogix.com"

                editableCxRum["session_context"] = sessionContext

            }

            return editableCxRum

        })
```

, and event discarding

```
let options = CoralogixExporterOptions(coralogixDomain: CORALOGIX-DOMAIN,

                                        environment: "ENVIRONMENT",

                                        application: "APP-NAME",

                                        version: "APP-VERSION",

                                        publicKey: "API-KEY",

                                        beforeSend: { cxRum in

            var editableCxRum = cxRum

            if var viewContext = editableCxRum["view_context"] as? [String: Any], 

                      let view = viewContext["view"] {

                if view == "DetailsViewController" {

                    return nil

                }

            }

        })
```

#### Masked interactions in `beforeSend` (`is_masked_element`)[​](#masked-interactions-in-beforesend-is_masked_element "Direct link to masked-interactions-in-beforesend-is_masked_element")

Every user-interaction event carries `interaction_context.is_masked_element` — the SDK's own observation that the interaction targeted **deliberately masked** content: a `cxMask` view, anything inside one, a SwiftUI `.cxMask()`, or a sensitive field. By default (matching the Browser SDK) only `target_element_inner_text` is redacted to `***` on a masked interaction; identity fields and coordinates are reported as-is. Anything stricter is yours to express here, where it stays auditable in your own code.

Session replay's pixel policy (`maskText`, `maskAllImages`) deliberately does **not** set this flag — it decides which pixels a frame hides, not whether text may leave the device, and treating it as the latter marks nearly every text tap as masked. So a tap on a `maskText`-matched label draws no replay marker yet reports `is_masked_element: false` with its real text. This matches the Android and Flutter SDKs. Use [`shouldSendText`](https://coralogix.com/docs/user-guides/rum/sdk-installation/apple/ios/configuration/swizzling-and-network-capture.md#user-action-text-redaction-shouldsendtext) if you want the pixel policy to withhold interaction text as well — note it applies to native interactions only, clicks, scrolls and swipes alike, since hybrid text arrives pre-resolved in the bridge payload; redact those in `beforeSend` or have the wrapper send `is_masked`.

Note

This applies from version 2.17.0. On earlier versions the pixel policy did set `is_masked_element` and redact the text for **UIKit** views, so a tap on a `maskText`-matched label reported `true` with `***`. Text inside SwiftUI content is masked by the OCR and Vision stages, which report no geometry, so it never set the flag on any version.

The flag is always present. `false` also covers "could not resolve" — a hybrid payload with no coordinates (React Native scroll/swipe), or no view hierarchy to walk (off the main thread, or no active foreground scene) — so it under-reports rather than over-reports when the SDK has no answer. Resolving it does **not** require session replay to be running.

Drop masked interaction events entirely:

```
beforeSend: { cxRum in

    let interaction = cxRum["interaction_context"] as? [String: Any]

    if interaction?["is_masked_element"] as? Bool == true {

        return nil

    }

    return cxRum

}
```

Or keep the event but blank the coordinates (they travel inside `interaction_context.attributes`):

```
beforeSend: { cxRum in

    var editable = cxRum

    if var interaction = editable["interaction_context"] as? [String: Any],

       interaction["is_masked_element"] as? Bool == true {

        var attributes = interaction["attributes"] as? [String: Any] ?? [:]

        attributes["x"] = 0

        attributes["y"] = 0

        interaction["attributes"] = attributes

        editable["interaction_context"] = interaction

    }

    return editable

}
```

`is_masked_element` itself is read-only: it records the SDK's observation, so a value written to it in the returned dictionary is ignored and the SDK's value is restored.
