# Analytics and owner settings

## Analytics

- `/dashboard/analytics` renders the owner analytics dashboard. `/dashboard/analytics/data` returns the authenticated owner's JSON report for 7, 30, or 90 days.
- Analytics queries are scoped to the store resolved from the signed-in owner. Product, category, hourly reports and product CSV require `advanced_analytics`; the report cache is per database, table prefix, store, range, and plan-access state with a five-minute TTL.
- `/analytics/track` reads the storefront store ID from the session, validates product ownership, and persists only daily HMAC hashes of IP address and user agent. Raw IP addresses and user agents are not written to analytics tables.
- Orders and top products can be downloaded as CSV. `tests/analytics_settings_test.php` exercises the authenticated JSON endpoint and prints its real report payload.

## Store settings

- General, WhatsApp, delivery, notifications, SEO, domain, policies, and account settings persist by `store_id` in `store_settings` or their owning tables. The old global `store.*` settings keys are not used by these workflows.
- WhatsApp numbers are validated as E.164; supported message placeholders are substituted in the order-success WhatsApp link.
- Delivery mode, fee, free-delivery threshold, and instructions feed checkout. The server recalculates and persists the method and fee; the checkout preview is only an estimate. Order PDFs include the delivery charge.
- New-order and low-stock notifications are called after order/stock updates. Daily summaries are idempotently claimed and sent from the daily cron through the existing `Mailer`/`mail_log`; plan expiry reminders honor the per-store preference.
- SEO settings produce store metadata, optional Store JSON-LD, and resized 1200×630 Open Graph images. `/sitemap.xml` and `/robots.txt` resolve the connected custom-domain store; `/{store_slug}/sitemap.xml` and `/{store_slug}/robots.txt` resolve that slug. Sitemap product queries are tenant-scoped.
- Policy pages are stored with the store's SEO page data and rendered by the existing storefront page route.
- Account settings support password changes, database-backed session listings and revocation, owner-scoped ZIP exports, and typed deletion requests held for 30 days. The daily cron processes expired holds. ZIP export uses ZipArchive when available and PharData otherwise.

## Verification

All integration suites below ran against isolated temporary MySQL databases and dropped their databases on completion:

- `tests/analytics_settings_test.php`: 37 checks passed, including JSON output, tenant isolation, plan gating, CSV exports, privacy-preserving tracking, notification send/replay behavior, sitemap isolation, session revocation, ZIP export, and deletion holds.
- `tests/checkout_flow_test.php`: 14 checks passed, including the configured delivery fee in the persisted order total and PDF.
- `tests/subscription_service_test.php`: 42 assertions passed.
- `tests/payments_test.php`: 32 checks passed.
- `tests/smoke.php`: all 11 HTTP steps passed.
- `tests/superadmin_test.php`: 84 checks passed.
- `tests/cron_access_test.php`: 2 checks passed.
- `php -l` passed on every changed PHP file; JavaScript syntax checks and `npm run build:css` passed. The CSS build noted that Browserslist data is outdated.

The analytics and settings test sends notification mail through an injected mock delivery callback. Payment and Super Admin mail tests also use mocks; no production SMTP delivery was performed.

## Domain limitation

The owner domain form stores a domain as `pending` and displays that DNS/SSL provisioning is unavailable in this flow. The repository did not contain the referenced N5 requirements, and no live DNS or SSL verification is claimed.
