# Geo Data Handling

Caller location in Retreaver — country, state, city, and zip — is stored as **geo tags** on the call and drives routing. Those values can come from several places: you can send them explicitly on an RTB Inbound Request or Data Writing request, Retreaver can infer them from the carrier or the caller's phone number (each controlled by a campaign toggle), callers can enter a ZIP in the IVR, or a webhook response can add or replace them while the call is still in progress.

This guide explains **each source**, **the order they apply**, how to **turn inference on or off per campaign**, and how **ZIP prompts** and **webhook responses** interact with geo that's already on the call.

---

## Quick reference — where geo comes from

| Source | When it applies |
| --- | --- |
| **RTB Inbound Request** | Reservation / pre-call ping |
| **Data Writing** | Before or during the call (stored, then applied) |
| **Carrier geo** | When a call starts |
| **Caller Number geo** | When a call starts |
| **Webhook responses** | Start, data-appending, enhance, post-zip pings |
| **ZIP prompt** | When routing |

---

## 1. RTB Inbound Request

When a publisher pings your RTB endpoint, they can supply location in the request body or query string.

**Common parameters:**

| Parameter | Effect |
| --- | --- |
|`caller_zip`| Sets the call's zip and adds a `geo` tag (`us-xxxxx`), plus city/state when Retreaver has that zip in its zip database |
|`geo`| Adds one or more geo tags (country `us`, state `us-co`, zip `us-90210`, area code `310`, etc.) |

These keys are **not** prefixed with your postback key name — they apply directly to the call.

**Example — explicit zip on RTB Inbound Request:**

```bash
curl -X POST "https://rtb.retreaver.com/rtbs.json?key=YOUR_POSTBACK_KEY&caller_number=17195551234&caller_zip=90210"
```

The reservation keeps `caller_zip=90210` even if the phone number would normally parse to a different zip, because RTB values are applied **before** caller-number inference.

**Example — geo tags without zip:**

```bash
curl -X POST "https://rtb.retreaver.com/rtbs.json?key=YOUR_POSTBACK_KEY&caller_number=17195551234&geo=us-ca"
```

Adds a California state geo tag. Combine with `caller_zip` when you need both.

> [!IMPORTANT]
> RTB geo is applied when the reservation is processed. It is **not** replaced by campaign toggles turning on carrier or caller-number inference later — those only fill **blank** fields at inbound connect time.
---

## 2. Data Writing request

The **Data Writing API** lets you attach tags to a caller **before** they connect (or during the call), keyed by caller number or call UUID.

**Whitelisted keys** (same as RTB): `geo`, `caller_zip`. Other keys are stored with your affiliate/postback prefix.

**How it flows:**

1. **Send tags** — POST to the Data Writing endpoint with the caller's phone number (or call UUID) and the geo you want (`caller_zip`, `geo`, etc.).
2. **Caller connects** — when that number calls in, Retreaver matches your data to the call.
3. **Applied before routing** — your tags are on the call before carrier or Caller Number geo can fill in anything still blank.

**Example — set zip before the caller dials:**

```bash
curl -X POST "https://retreaverdata.com/data_writing?key=YOUR_KEY&caller_number=17195551234&caller_zip=33172"
```

When the call comes in, `33172` is on the call before carrier or phone inference runs.

> [!IMPORTANT]
> Data Writing treats `caller_zip` and `geo` the same way as RTB: `caller_zip` sets the zip on the call and adds geo tags; `geo` adds geo tag values. If you send the same key more than once, the newest value wins.
---

## 3. Caller Number geo information

Open a campaign → **Toggles** tab → **Geo Data Handling** card. **Use Caller Number geo information** defaults to **on**.

![](/media/68/68df20c7d9427769b4ddae3531536d07096cf40bb0a02efff6cc31109112c757.png)

Use geo location tags extracted from the caller number (country, state, city, zip code) unless already supplied via an RTB Inbound Request, a Data Writing request, or extracted from the carrier (see **Use carrier geo information** in the next section).

**When on:** when the call comes in, Retreaver parses the caller's phone number and may set city, state, country, zip, and `geo` tags such as `us`, `719`, `us-co`.

**Example:**

An inbound caller dials your tracking number from `+1 719 522 8888`. With **Use Caller Number geo information** on, Retreaver can fill in location from the phone number — for example, zip `80918` and matching geo tags — unless the call already has geo from an RTB Inbound Request, Data Writing, or the carrier.

**When off:** Retreaver does not look up location from the phone number. No city, state, country, zip, or phone-derived `geo` tags are added from the number alone. Carrier geo can still apply if **Use carrier geo information** is on.

![](/media/3e/3e7e12957558bcb76ccc996c95e2d2ddaa356d10a6b36a1a6bd0ed1ae84df39c.png)

**Example:**

An inbound caller dials your tracking number from `+1 719 522 8888`. With **Use Caller Number geo information** off, Retreaver does not add zip `80918` or other location from the phone number. Zip and geo tags stay blank unless another source supplies them — for example, the carrier if **Use carrier geo information** is on.

---

## 4. Carrier supplied geo information

**Use carrier geo information** is on the same **Geo Data Handling** card and also defaults to **on**.

![](/media/0d/0d0c31cd8ca3e146519817ec6277d7e3ea5a6b49dccc5c717f7c1bc78341746a.png)

Use geo location tags from the carrier (country, state, city, zip code) unless already supplied either via an RTB Inbound Request or via a Data Writing request.

**When on:** when the call comes in, inbound and click-to-call legs read carrier webhook fields (city, state, country, zip on the caller's leg) and populate any blank location fields.

**Example:**

An inbound caller dials your tracking number and the carrier reports Denver, CO and zip `80202`. With **Use carrier geo information** on, Retreaver uses those carrier values to fill in any blank location fields on the call.

**When off:** carrier city, state, country, and zip are ignored.

![](/media/56/56d217525bebfb6808e42c80547ee9b162a6c41669036d4531e4372c811d9cd9.png)

**Example:**
An inbound caller dials your tracking number and the carrier reports Denver, CO and zip `80202`. With **Use carrier geo information** off, Retreaver ignores those values and if the call DOES NOT have any geo information from an RTB Inbound request or a Data-Writing request, it's geo information, such as `caller_zip` will be **empty**.

> [!IMPORTANT]
> On an **RTB Inbound Request** (before the caller dials), carrier information IS NOT used. This information is only applied when we actually received a call.
---

## 5. Geo information appended by webhooks

**Start**, **data-appending** and any other type of webhook can return tags in the JSON response. Retreaver will take those tags and apply them on the call right after the webhook has completed.

### Overwriting existing geo

When a webhook returns `caller_zip` or a zip-style `geo` value (`us-xxxxx`), Retreaver **replaces the existing geo tags on the call** (country, city, state, zip) with the ones returned from the webhook.

> [!INFO]
> **Retreaver IQ:** [Retreaver IQ by Audience Acuity](https://learn.retreaver.com/guides/retreaver-iq-zip-code-solutions) is a built-in enrichment integration that can populate `caller_zip` and related geo on inbound calls — via a **Data Append** webhook for ping-first workflows.

**Example:**

Your call already has `caller_zip=33172` from Data Writing. A **Data Append** webhook (including Retreaver IQ) returns `caller_zip=90210`. Retreaver updates the call’s zip to `90210` and replaces its geo tags with the matching geo for `90210`.

### Opting out of overwriting existing geo information

Sometimes you don't want the geo information data to be overwritten by new geo information from webhooks. In that case you can opt out of that behavior by simply not firing the webhook in the first place.

**Example — webhook that only enriches calls missing zip:**

You want a **start webhook** to run enrichment only when the call has **no zip yet** — e.g. skip when RTB already sent `caller_zip`.

Configure the webhook timer's tag rules (or the buyer's forward tags, depending on your setup) with:

```
caller_zip!~.+
```

This means “the call does **not** have a `caller_zip` tag with any value yet.”

Pair that rule with a webhook response that returns geo information, so:
 - calls that already have zip from RTB or Data Writing won't match `caller_zip!~.+` and won't be sent to that enrichment path.
 - calls without zip will match and receive the webhook's geo.

---

## 6. ZIP prompt

Campaign **Prompts** can ask US callers to enter a 5-digit ZIP before routing. Two prompt types:

### ZIP code entry — unless already present

**Prompt action:** `ZIP code entry — unless already present`

**When it plays:** the caller is US-based **and** the call has **no** `geo` tag matching `us-xxxxx` (no zip geo tag yet).

**When it skips:** RTB, Data Writing, carrier, caller-number, or an earlier webhook already left a zip geo tag on the call.

Use this when you only need to collect zip from callers who didn't provide it upstream.

### ZIP code entry — always

**Prompt action:** `ZIP code entry — always`

**When it plays:** every US caller who has **not** yet completed this campaign's "always" ZIP IVR in the current flow — **even if** zip geo is already on the call from RTB, Data Writing, carrier, or phone parsing.

**When enabled:** requires the **ZIP IVR always** feature for your campaign (contact Retreaver support or your account manager to enable).

**Overrides existing geo:** a valid 5-digit entry calls the same `set_zip` path as `caller_zip` / `geo:us-xxxxx` — clearable geo tags are replaced and city/state/zip columns update. If the caller enters an invalid zip, the always prompt may clear stale zip/geo from a prior override before re-prompting.

**Precedence vs "unless already present":** if both prompts exist and **always** is enabled for the campaign, **always** wins.

**After ZIP entry:** if you configure **post-zip** webhooks, they fire after a successful entry (with a brief ring while pings run) before routing continues.

---

## Practical workflows

### Publisher sends zip on RTB — don't guess over it

1. Publisher includes `caller_zip=90210` on every RTB Inbound Request.
2. Leave **Use Caller Number geo information** and **Use carrier geo information** on (default).
3. Retreaver keeps `90210` from the RTB Inbound Request; caller-number parsing does not replace it.

### Stop phone zip guessing, keep carrier city/state

1. Turn off **Use Caller Number geo information** on the Geo Data Handling card.
2. Leave **Use carrier geo information** on.
3. Inbound calls still get carrier city/state/country; zip and geo tags from phone parsing are not added.

### Collect zip on every call for compliance

1. Ask Retreaver to enable **ZIP IVR always** for the campaign.
2. Add prompt **ZIP code entry — always** to the campaign.
3. Callers hear the ZIP prompt before routing even when RTB sent a zip — their entry **replaces** prior zip/geo.

### Enrich only calls missing zip via start webhook

1. Add a start webhook timer with tag rule `caller_zip!~.+`.
2. Return `caller_zip` or `geo:us-xxxxx` in the JSON response when your enrichment service finds a zip.
3. Leave **Use Caller Number geo information** on as a fallback for calls the webhook doesn't match.

---

## Key takeaways

* **You control** geo via RTB `caller_zip` / `geo` and Data Writing — those win over automatic inference.
* **Campaign toggles** independently control carrier geo and caller-number geo (both default on).
* **Webhooks** can add or **overwrite** geo during ping rounds; `caller_zip` / zip-style `geo` responses clear and replace clearable geo tags.
* **`caller_zip!~.+`** is the tag rule for "no zip present yet" when configuring enrichment or routing.
* **ZIP unless present** skips when zip geo already exists; **ZIP always** plays regardless and overrides — when the feature is enabled for your campaign.
* **Upstream calls** copy geo from the parent call; toggles don't apply there.
