---
title: "Halo correlation and incremental lift"
method: POST
path: "/halo/analysis"
tags: ["Halo Effect Tracker"]
---

# Halo correlation and incremental lift

`POST /halo/analysis`

The flagship halo read — how much off-TikTok revenue moved with TikTok activity over the window, and how confidently that can be claimed. Four things come back: 

**summary** — ``base_sales`` is the average daily Amazon+Shopify revenue over the 30 days immediately BEFORE the window (the pre-period run rate). ``incremental_revenue`` is the window's revenue minus that run rate carried across the days that have data — the revenue above baseline, and the number to quote as halo lift. It goes negative when the window underperformed the prior 30 days. ``relationship_strength`` is the Pearson r between daily TikTok views and daily combined off-platform revenue; ``views_explain`` is r squared, readable as 'views explain N% of the day-to-day revenue swing'. 

**channel_correlations** — the same regression per off-platform channel, each with ``r``, a two-sided ``p_value`` (below 0.05 is the usual bar for calling it real) and a plain-English ``label``. TikTok GMV is deliberately absent: it is driven by the same views it would be correlated against, so it correlates by construction and is direct attribution, not halo. It appears under ``attribution`` instead. 

**branded_search_correlation** — TikTok views vs Amazon branded search, the earliest and cleanest halo signal. Null when the shop has no branded-search tracking. 

**attribution** — raw revenue sums per channel for the window, unmodelled. 

``lag_days`` shifts TikTok views forward before correlating, so a video today can be matched against an Amazon order three days later; sweep 0-14 and keep the strongest r. Any r is null when fewer than 5 aligned day-pairs have data on both sides, or when a channel is not connected — check ``GET /halo/channels`` first. Correlation is not causation: a strong r with a plausible lag is evidence, not proof. 

Defaults to the last 30 days ending yesterday; max 366, though TikTok views are only daily-resolved for the most recent ~30 days, so wider windows weaken the regression rather than strengthen it. Single-shop only.

## Request body

- HaloAnalysisRequest — POST /halo/analysis body — the window plus the lag to test.
  - `start_date` string, date, nullable — Inclusive window start (YYYY-MM-DD). Defaults to 29 days before ``end_date`` (a 30-day window). Max window 366 days.
  - `end_date` string, date, nullable — Inclusive window end (YYYY-MM-DD). Defaults to yesterday — today's revenue rows have not been pulled yet.
  - `amazon_asins` string[], nullable — Restrict Amazon revenue and branded search to these ASINs. Omit for the shop total. Values come from ``GET /halo/products``.
  - `shopify_product_ids` string[], nullable — Restrict Shopify revenue to these product IDs. Omit for the shop total. Values come from ``GET /halo/products``.
  - `lag_days` integer — Shift TikTok views forward N days before correlating, to test a delayed halo (a video today, an Amazon order three days later). 0 correlates same-day. Sweep 0-14 and keep the strongest r.

## Response `200`

Successful Response

- HaloAnalysisResponse
  - `shop_id` integer, required
  - `start_date` string, required
  - `end_date` string, required
  - `lag_days` integer, required
  - `summary` HaloAnalysisSummary, required
    - `base_sales` number, nullable — Average daily Amazon+Shopify revenue over the 30 days BEFORE the window — the pre-period run rate the window is measured against.
    - `incremental_revenue` number, nullable — Window revenue minus (``base_sales`` x days with data) — the revenue above the pre-period run rate. Negative means the window underperformed the baseline.
    - `relationship_strength` number, nullable — Pearson r between TikTok views and combined off-platform revenue at the requested lag. Null when fewer than 5 aligned day-pairs have data on both sides.
    - `views_explain` number, nullable — r-squared — the share of day-to-day revenue variance that moves with TikTok views. 0.42 reads as 'views explain ~42% of it'.
  - `channel_correlations` HaloCorrelation[], required — Per-channel Pearson results for the off-platform channels only. TikTok GMV vs TikTok views is excluded — both are driven by the same activity, so it correlates by construction and is not halo.
    - `channel` string, nullable
    - `r` number, nullable — Pearson r, 4 dp.
    - `p_value` number, nullable — Two-sided p-value, 6 dp. Below 0.05 is the usual bar.
    - `label` string, nullable — Very Weak / Weak / Moderate / Strong / Very Strong.
  - `branded_search_correlation` HaloCorrelation
    - `channel` string, nullable
    - `r` number, nullable — Pearson r, 4 dp.
    - `p_value` number, nullable — Two-sided p-value, 6 dp. Below 0.05 is the usual bar.
    - `label` string, nullable — Very Weak / Weak / Moderate / Strong / Very Strong.
  - `attribution` HaloAttribution, required
    - `tiktok_gmv` number, nullable
    - `amazon` number, nullable
    - `shopify` number, nullable
    - `total` number, nullable

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.dev/reacherapp/apis/reacher-data-api.md) · [All operations](https://skmtc.dev/reacherapp/apis/reacher-data-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/reacherapp/reacher-data-api/revisions/d4fe3e380424/schema)
