> For the complete documentation index, see [llms.txt](https://docs.openg2p.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openg2p.org/platform/platform-services/reporting-and-analytics/map-drill-down.md).

# Map drill-down

The choropleth that drills from region to district to ward — where its figures come from, and how a country changes what it shows.

The map surface renders one choropleth per administrative level and lets a reader click down through the hierarchy — region, then the districts within it, then the wards within that — with linked figures beside the map re-filtering as they go.

It reads the same [reporting views](/platform/platform-services/reporting-and-analytics/reporting-views.md) as the dashboards. What makes it a map rather than a chart is one join: **each area's figures are matched to its shape on P-code**, never on name.

## What the registry supplies

A registry ships a small content bundle, published as a ConfigMap during its install:

```
maps/
  sources/
    level1_summary.sql      one row per first-level unit
    level2_summary.sql      one row per second-level unit
    level3_summary.sql      one row per third-level unit
    level2_commodities.sql  a breakdown panel
  pages/
    index.md                the page: maps, tiles, charts
```

Each source is an aggregate over a reporting view, and every one of them must return three columns with these names:

| Column         | Is                                                      |
| -------------- | ------------------------------------------------------- |
| `pcode`        | the unit's P-code — what the shape is joined on         |
| `parent_pcode` | its parent's P-code — what makes drilling down possible |
| `area_name`    | the unit's name, for display only                       |

Everything else in the query is measures.

{% hint style="warning" %}
**Nothing may be called `name`.** The map component's input is a callable, and a field called `name` collides with a function's own `name` property — which kills the map outright rather than producing a warning. Use `area_name`.
{% endhint %}

## Why the files are named by depth

`level1_summary.sql`, not `region_summary.sql`. "Region", "zone", "woreda" are Ethiopian; a Philippines pack has Region, Province, Municipality, Barangay, and an Indian one has State and District.

The reporting views unpack geography **positionally** into `geo_1..geo_N`, so the same query works for any country's pack. `<prefix>_rpt_geo_levels` carries this deployment's own level labels, so a page can title its columns correctly without anything in the SQL naming a country.

## Adding a measure

Add it to the `SELECT` in the level file, then reference it on the page. A measure is any aggregate over the view:

```sql
count(*)                                                as farmers,
round(100.0 * avg(case when is_female then 1 else 0 end), 1) as pct_female,
count(*) filter (where has_land and not has_any_title)  as no_title_farmers
```

{% hint style="info" %}
**Prefer counts to rates for anything an officer should act on.** A rate needs a denominator large enough to survive one record moving; a count is exact whether the area holds twelve records or twelve thousand, needs no suppression, and sums up the hierarchy. "318 farmers holding land with no title" is a work order; "62.1% titled" is not.
{% endhint %}

## Adding a level, or working with a different depth

Levels are bounded by the country pack. A four-level pack gives `geo_1..geo_4`, and a source file that references `geo_5` returns nothing.

To add a level, copy the deepest existing file, shift the `geo_N` references down one, and add the corresponding section to `index.md`. The shapes come from the pack (see [Where the shapes come from](#where-the-shapes-come-from)), so a level with no boundary file in the pack has no map to draw, whatever the SQL returns.

## Where the shapes come from

Master Data uploads the pack's boundary files, one GeoJSON per level, to the object store when it is seeded. The **map build** asks Master Data where this deployment's files are and fetches them **at build time**, then publishes them with the figures it extracts from the reporting views.

So the shapes follow the deployment's country pack: reseed Master Data with another pack and rebuild the map. No image is rebuilt.

{% hint style="warning" %}
**Shapes and figures must come from the same pack.** The map joins them on P-code. Shapes from one country beside figures from another render an **empty map**, with no error: every join misses. If the build cannot reach Master Data, it falls back to the shapes baked into its image (the default pack) and logs a warning; for any other country that also gives an empty map. Check the map after any pack change.
{% endhint %}

## Changing what the map shows

`index.md` is the page. It decides which measure colours each choropleth, which appear as headline figures, and what the breakdown panels are. Editing it is how you change the surface without touching any SQL.

## Getting your version deployed

The content bundle lives in your registry's repository and is published as a ConfigMap by the registry's chart. The map build is told which ConfigMap to read.

{% hint style="danger" %}
**If that setting is left empty the build falls back to reference content**, and compiles the reference registry's queries against your registry's database. Every query fails, and the result is a complete, correctly themed site with every panel empty — which reads as "no data yet" rather than as a misconfiguration. Set it explicitly.
{% endhint %}

A country that wants its own map content publishes its **own** ConfigMap and points the build at it — no fork of the registry or the platform is needed, and no image is rebuilt.

## What the map cannot do

* **Show more than one registry at once.** One map surface reads one registry's views. A combined view across registries is not supported today.
* **Drill below the pack's deepest level**, or to individual records. The map is an aggregate surface; record-level questions belong in a dashboard or an ad-hoc query.

***

**See also:** [Reporting views](/platform/platform-services/reporting-and-analytics/reporting-views.md) · [Country Packs](/platform/platform-services/master-data-service/country-packs.md) for P-codes, boundary files and how packs are built.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.openg2p.org/platform/platform-services/reporting-and-analytics/map-drill-down.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
