# Data model

Each Shopify store's homepage is read **once a week** with one plain GET (no browser), and an app counts as present when its web pixel, theme app embed, script or markup is found there.

## Detection

| Evidence | What we found | Strength |
| --- | --- | --- |
| `webPixel` | The app's Shopify web pixel, identified by its Partner app id | Strongest |
| `themeAppExtension` | An app embed in the theme | Strong |
| `script` | A ScriptTag or third-party script on the page | Good |
| `html` | Markup the app writes into the page | Good |

Each app on a store lists its evidence (`evidence`), so you can check it in the page source. Apps a tag manager injects only at runtime are not seen.

## Store status

A store's `status` is the latest scan's verdict. Apps come from the latest `live` scan (`lastHealthyScanAt`), so a store that is briefly unreachable keeps its last known stack.

| Status | Meaning |
| --- | --- |
| `live` | Read the storefront |
| `password` | Behind a password page |
| `closed` | The store is unavailable |
| `not_shopify` | The domain no longer serves a Shopify store |
| `unreachable` | We could not read the page this time |

## Dates

- `firstSeenAt` / `lastSeenAt` on an app: the first and latest scans that found it.
- An **event** ([`GET /v1/events`](https://installgraph.com/docs/reference/list-events.md)) happened between `previousScanAt` and `detectedAt`. A store's first scan reports no installs (we cannot say when they happened). Removals are inferred only from a scan that read the whole live page.
- `theme.since`: the first scan on the current theme.

## Store attributes

| Field | What it is |
| --- | --- |
| `country` | ISO 3166-1 alpha-2 country the store sells from (Shopify's `Shopify.country`) |
| `region` | `north-america`, `latin-america`, `europe`, `middle-east-africa` or `asia-pacific` |
| `industry` | Our reading of the homepage, in the Store Leads taxonomy: 26 categories, 182 subcategories, with `confidence` |
| `pricePoint` | Typical order value as a USD band (`under-25`, `25-50`, `50-100`, `100-200`, `200-500`, `500-1000`, `1000-plus`), from homepage product prices |
| `theme` | Theme name, version, Theme Store id, and the merchant's name for their copy |
| `customPixelCount` | Custom pixels in Shopify's Customer events |

[`GET /v1/industries`](https://installgraph.com/docs/reference/list-industries.md) lists every industry, region (with its countries) and order-value band the filters accept.

## Filters

`country`, `region`, `industry` and `aov` work on [`GET /v1/apps/{slug}/companies`](https://installgraph.com/docs/reference/list-app-companies.md), its count, and [`GET /v1/events`](https://installgraph.com/docs/reference/list-events.md). Combined filters must all hold.

- `industry=Apparel` matches the category and every subcategory; `industry=Apparel/Footwear` matches one subcategory.
- `aov` takes one or more bands, comma-separated: `aov=100-200,200-500`.

## App categories

Our own categories for apps (not the App Store's), used by [`GET /v1/apps`](https://installgraph.com/docs/reference/list-apps.md) and [`GET /v1/public/stats`](https://installgraph.com/docs/reference/get-public-stats.md):

`ads-pixel`, `analytics`, `tag-management`, `server-side-tracking`, `attribution`, `email-sms`, `reviews`, `loyalty`, `subscriptions`, `search`, `upsell-personalisation`, `popups`, `support-chat`, `consent`, `accessibility`, `shipping-protection`, `returns-tracking`, `fraud`, `payments-bnpl`, `affiliate`, `wishlist`, `back-in-stock`, `translation`, `page-builder`, `ab-testing`, `cross-border`, `product-feeds`, `other`.
