> ## Documentation Index
> Fetch the complete documentation index at: https://docs.appeeky.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Organic Search Performance

> Branded vs non-branded keyword visibility, search downloads by keyword, and a store funnel that explains why organic downloads moved.

**Organic search performance** joins your keyword ranks with your store analytics for an app you own. It answers three questions:

* **Is my search visibility growing, and is it only my brand name?** Visibility is split into branded and non-branded keywords.
* **Which keywords bring downloads?** Search downloads are broken down by keyword.
* **Why did organic downloads change?** A daily funnel from impressions to downloads, with a one-line diagnosis: reach, conversion or both.

In the dashboard this is the **Organic** view in **ASO Intelligence → Store Performance**. Visibility also appears in **ASO Intelligence → Keyword Intelligence → Visibility**.

> [!NOTE]
>
> Requires a paid plan. Reads cost **2 credits**; saving brand terms is free. Downloads and funnel data need your [App Store Connect](https://docs.appeeky.com/docs/app-store-connect-overview.md) or [Google Play](https://docs.appeeky.com/docs/google-play-connect.md) account connected. Without it you still get visibility and keyword shares.

***

## API

| Method | Endpoint | Description |
| - | - | - |
| GET | `/v1/connect/organic/visibility-trend` | Daily visibility, split into branded and non-branded |
| GET | `/v1/connect/organic/keyword-downloads` | Search downloads per keyword, with change vs the previous period |
| GET | `/v1/connect/organic/timeline` | Daily store funnel, period totals and a diagnosis |
| GET | `/v1/connect/organic/brand-terms` | The terms that count as your brand |
| PUT | `/v1/connect/organic/brand-terms` | Replace your brand terms |

Every endpoint takes:

| Name | Type | Required | Default | Description |
| - | - | - | - | - |
| `platform` | string | No | `apple` | `apple` or `google` |
| `storeAppId` | string | Yes | — | App Store numeric id or Google Play package name |
| `appName`, `developerName` | string | No | — | Used to build default brand terms when you haven't saved any |
| `country` | string | No | `us` | Storefront for ranks. On `/timeline`, `all` (default) or a country code; see below |
| `days` | number | No | `30` (`28` on `/timeline`) | One of `7`, `14`, `28`, `30`, `60`, `90` |

***

## Brand terms

A keyword counts as **branded** when it contains one of your brand terms as whole words ("example habits app") or matches it with spaces removed ("examplehabits"). By default the terms come from your app title's brand name and your developer name.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl -X PUT https://api.appeeky.com/v1/connect/organic/brand-terms \
  -H "X-API-Key: $APPEEKY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "platform": "apple", "storeAppId": "123456789", "terms": ["example habits", "examplehabits"] }'
```

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{ "data": { "terms": ["example habits", "examplehabits"], "source": "user", "defaults": ["example habits", "example inc"] } }
```

Up to 30 terms. Send `"terms": []` to go back to the defaults (`source: "default"`).

***

## Visibility trend

`GET /v1/connect/organic/visibility-trend?storeAppId=123456789&country=us&days=30`

Each day in `series` has the overall `score`, `rankedCount`, and how many keywords rank in the top 3, 10 and 30, plus the same numbers for `branded` and `nonBranded` keywords. `brandShare` (0–1) is the part of your visibility that comes from branded keywords. A high `brandShare` means people mostly find you by name.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "data": {
    "platform": "apple",
    "storeAppId": "123456789",
    "country": "us",
    "days": 30,
    "segmented": true,
    "brandTerms": { "terms": ["example habits"], "source": "default", "defaults": ["example habits"] },
    "series": [
      {
        "date": "2026-10-31",
        "score": 31.4,
        "rankedCount": 214,
        "top3": 6,
        "top10": 18,
        "top30": 57,
        "branded": { "score": 9.2, "rankedCount": 4, "top3": 3, "top10": 4, "top30": 4 },
        "nonBranded": { "score": 22.2, "rankedCount": 210, "top3": 3, "top10": 14, "top30": 53 },
        "brandShare": 0.29
      }
    ]
  }
}
```

***

## Downloads by keyword

`GET /v1/connect/organic/keyword-downloads?storeAppId=123456789&country=us&days=30`

How the numbers are made depends on the store, shown in `mode`:

| `mode` | Meaning |
| - | - |
| `reported` | Google Play: acquisitions per search term as reported by Play Console, matched to your rank in the chosen country |
| `estimated` | App Store: App Store Connect reports search downloads only for the whole app, so Appeeky splits them across your ranked keywords by search popularity and your rank. Untracked keywords aren't included, so figures lean high |
| `share_only` | No store data connected. Only each keyword's estimated `share` is returned; `downloads` is `null` |

The response also includes `method`, a plain-language version of the above that you can show to users.

Each row has `keyword`, `rank`, `volumeScore`, `isBrand`, `share` (0–1 of search downloads), `downloads`, `visitors` (Google Play only), `previousDownloads` and `changePct`. Totals at the top: `totalSearchDownloads`, `brandShare`, `brandDownloads`, `nonBrandDownloads`, and on Google Play `rankedCoverage` (share of search acquisitions from terms you rank for).

***

## Funnel timeline

`GET /v1/connect/organic/timeline?storeAppId=123456789&country=all&visibilityCountry=us&days=28`

`country` scopes the store funnel: `all` (default) for worldwide, or a country code. Visibility always needs one storefront, taken from `country` or, when `country=all`, from `visibilityCountry` (default `us`).

Each day in `series` has `visibility`, `impressions` (App Store only), `pageViews`, `downloads`, `installs` (Google Play only) and `conversionRate`. `current` and `previous` hold totals for this period and the one before it.

`diagnosis` explains the change between the two periods:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "driver": "conversion",
  "direction": "down",
  "downloadsChangePct": -0.18,
  "reachChangePct": 0.02,
  "conversionRateChangePts": -1.4,
  "visibilityChange": 0.6,
  "reachShare": null,
  "headline": "Downloads fell 18%",
  "details": ["Reach held steady, but fewer visitors downloaded."]
}
```

`driver` is `reach`, `conversion`, `both`, `stable` or `insufficient_data`. `notes` lists caveats, for example that App Store Connect doesn't split impressions by country.

***

## Errors

| Status | Code | When |
| - | - | - |
| 400 | `INVALID_APP_ID` | `storeAppId` doesn't match the platform's id format |
| 400 | `INVALID_PLATFORM` | `platform` is not `apple` or `google` |
| 400 | `INVALID_COUNTRY` | `/timeline` `country` is not `all` or a 2-letter code |
| 400 | `INVALID_BODY` | Brand terms body is invalid |
| 403 | `PRO_FEATURE` | Your plan doesn't include this feature |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.