← back to Rentv Adintel
docs/EXPORT_FORMAT.md
75 lines
# RENTV Advertiser Intelligence — Export Format
The one-click **Download Everything** action (§28) produces a single ZIP. It runs through
a job with visible progress (large exports are never streamed unbounded in one request),
and every file honors suppression, do-not-contact, private notes, and source rights.
## ZIP manifest (§28)
```text
RENTV-Advertiser-Intelligence-YYYY-MM-DD/
executive-viewer.html # self-contained offline viewer (double-click to open)
README.html # what's in the export + how to read it
advertisers.csv # the advertiser table
advertisers.xlsx # same, Excel workbook
contacts.csv # public business contacts (rights-filtered)
contacts.xlsx
ad-sightings.csv # verified ad/sponsor sightings + evidence pointers
creatives.csv # creative assets metadata (export-allowed only)
conference-sponsors.csv # event ↔ organization sponsor/exhibitor rows
conferences.csv # events list
prospects.csv # ranked RENTV opportunities + score factors
analytics-summary.csv # GA4/GSC rollup (DEMO or LIVE, labeled)
ga4-landing-pages.csv
ga4-geography.csv
gsc-queries.csv
gsc-pages.csv
google-ads-campaigns.csv # ONLY when Google Ads is connected
source-manifest.json # every source + policy + access method + review date
methodology.json # score weights, formulas, classification definitions
export-audit.json # who exported, when, row counts, rights filters applied
thumbnails/ # web thumbnails for export-allowed creatives
evidence/ # ONLY assets flagged export-allowed (never internal-only)
database-readonly.sqlite # optional portable snapshot (never a second source of truth)
```
`google-ads-campaigns.csv` appears only when the Google Ads connector is configured. The
SQLite snapshot is an **export artifact only** — PostgreSQL remains the canonical source
of truth.
## `executive-viewer.html` behavior
A self-contained, read-only HTML file for handing to a non-technical stakeholder:
- **Works by double-clicking it** — no server, no build step, no network.
- Uses only **relative local assets** inside the ZIP folder.
- Provides **in-browser search and filters** over the advertiser data (California /
Arizona / All, Verified Only).
- Shows **advertiser cards + thumbnails** with status badges (text, not color-only).
- Opens every **source link in a new tab**.
- Shows the **data date and source coverage** so the reader knows how fresh it is.
- **Omits internal-only evidence images** — only export-allowed thumbnails are embedded.
- Is **accessible and printable**.
## Rights filtering applied to every export
`applyExportRights(rows, kind)` (`src/export/rights.js`) is the single choke point every
dataset passes through before it is written. It removes:
- **suppressed** rows — organizations/people named in an active suppression request
(matched by id via a suppression set the caller builds from `suppression_requests`),
- **do-not-contact** contacts and any contact with `export_allowed = false`,
- **private notes** (`is_private = true`).
For **creative assets**, the metadata row is retained but the image bytes are gated by
`rights_status`: `EXPORT_ALLOWED` → bundle the file in `thumbnails/`;
`INTERNAL_EVIDENCE_ONLY` / `LINK_ONLY` / `UNKNOWN` → **omit the bytes**, keep only a
link-only placeholder (each row is annotated with an `_exportClass` of `include` or
`link_only`). So an internal-only image's pixels never leave the app even though its
citation remains.
`test/export-filter.test.js` locks each of these in (including that no
`INTERNAL_EVIDENCE_ONLY` or `UNKNOWN`-rights asset is ever classified `include`). Because
the same helper gates the CSV/XLSX rows, the `evidence/` folder, and the offline viewer,
an internal-only image or a suppressed company cannot leak through any one path.