Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.tryprofound.com/llms.txt

Use this file to discover all available pages before exploring further.

A real dashboard tile shows two numbers: the headline period score (one big number) and the daily series (the line). These come from two separate calls to the same endpoint. This recipe runs both side-by-side and explains how each is extracted and why you can’t derive one from the other.
Don’t average daily rows to derive a period score — they’re computed differently. See Conventions & gotchas.

How this example works

  1. Headline call has no date dimension. The API returns a single traffic-weighted score for the whole window.
  2. Series call adds date to dimensions and sets date_interval. The API returns one row per day, each containing that day’s unweighted rate.
  3. Don’t average the daily values to compute the headline. Days with more prompts count more in the headline; the daily mean treats every day equally. The two are computed differently on purpose.
import os
from profound import Profound

client = Profound(api_key=os.environ["PROFOUND_API_KEY"])

# What to fetch — replace with your own values.
CATEGORY_NAME = "<your-category-name>"
ASSET_NAME    = "<your-asset-name>"
START_DATE    = "2026-05-05"
END_DATE      = "2026-05-12"   # exclusive — returns data through 2026-05-11


def get_headline_score(category_id, asset_name, start_date, end_date):
    """Traffic-weighted period score (no date dim)."""
    res = client.reports.visibility(
        category_id=category_id,
        start_date=start_date,
        end_date=end_date,
        metrics=["visibility_score"],
        filters=[{"field": "asset_name", "operator": "is", "value": asset_name}],
    )
    order = res.info.query["metrics"]
    return res.data[0].metrics[order.index("visibility_score")]


def get_daily_series(category_id, asset_name, start_date, end_date):
    """One (date, score) point per day — for the line chart."""
    res = client.reports.visibility(
        category_id=category_id,
        start_date=start_date,
        end_date=end_date,
        metrics=["visibility_score"],
        dimensions=["date"],
        date_interval="day",
        filters=[{"field": "asset_name", "operator": "is", "value": asset_name}],
    )
    m_order = res.info.query["metrics"]
    d_order = res.info.query["dimensions"]
    i_score = m_order.index("visibility_score")
    i_date  = d_order.index("date")
    points = [
        (row.dimensions[i_date], row.metrics[i_score])
        for row in res.data
    ]
    return sorted(points, key=lambda p: p[0])


# Helpers — translate human-readable names into the IDs the report API needs.

def find_category_id(name):
    """Return the UUID of the category whose name matches (case-insensitive)."""
    for c in client.organizations.categories.list():
        if c.name.lower() == name.lower():
            return c.id
    raise ValueError(f"No category named {name!r}")


def find_asset_name(category_id, name):
    """Return the canonical asset name (case-insensitive) inside the category."""
    for a in client.organizations.categories.assets(category_id):
        if a.name.lower() == name.lower():
            return a.name
    raise ValueError(f"No asset named {name!r} in this category")


# Resolve names → IDs, then run both calls.
category_id = find_category_id(CATEGORY_NAME)
asset_name  = find_asset_name(category_id, ASSET_NAME)

headline_score = get_headline_score(category_id, asset_name, START_DATE, END_DATE)
daily          = get_daily_series(category_id, asset_name, START_DATE, END_DATE)

print(f"Headline: {headline_score:.1%}\n")
print("Daily:")
for date, score in daily:
    print(f"  {date}  {score:.1%}")

How the two responses differ

Headline callSeries call
dimensions[]["date"]
date_intervalnot sent"day" (or week/month)
Rows returned1N (one per bucket)
Score per rowTraffic-weighted across the windowUnweighted within that day
Used forThe big KPI numberThe line on the chart

Why you can’t average the daily values

The headline weights days by their prompt volume — a day with 10,000 prompts moves the headline more than a day with 100. Averaging daily rates treats those two days as equal. For most assets the gap is 1-3 percentage points; for assets with bursty traffic it can be more. Always use the headline call for the headline.