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.

The multi-line “your asset vs competitors” chart in the Profound app is one call. Add asset_name to dimensions to get per-asset rows, and use an in filter to limit to the assets you care about.
Don’t average daily rows to derive a period score — they’re computed differently. See Conventions & gotchas.

How this example works

  1. dimensions: ["date", "asset_name"] — one row per (date, asset).
  2. filters with in operator — limit to a hand-picked set of assets. Without the filter you’d get every asset in the category.
  3. Pivot the response into one series per asset before plotting.
import os
from collections import defaultdict
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>"
ASSETS        = ["<your-asset>", "<competitor-1>", "<competitor-2>", "<competitor-3>"]
START_DATE    = "2026-05-05"
END_DATE      = "2026-05-12"   # exclusive — returns data through 2026-05-11


def get_competitor_series(category_id, asset_names, start_date, end_date, interval="day"):
    """Daily Visibility Score for each asset in `asset_names`. Returns {asset: [(date, score), ...]}."""
    res = client.reports.visibility(
        category_id=category_id,
        start_date=start_date,
        end_date=end_date,
        metrics=["visibility_score"],
        dimensions=["date", "asset_name"],
        date_interval=interval,
        filters=[{"field": "asset_name", "operator": "in", "value": asset_names}],
    )
    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")
    i_asset = d_order.index("asset_name")

    by_asset = defaultdict(list)
    for row in res.data:
        by_asset[row.dimensions[i_asset]].append(
            (row.dimensions[i_date], row.metrics[i_score])
        )
    for asset in by_asset:
        by_asset[asset].sort(key=lambda x: x[0])
    return by_asset


# 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_names(category_id, names):
    """Return the canonical names for each input name (case-insensitive)."""
    by_lower = {
        a.name.lower(): a.name
        for a in client.organizations.categories.assets(category_id)
    }
    out = []
    for n in names:
        if n.lower() not in by_lower:
            raise ValueError(f"No asset named {n!r} in this category")
        out.append(by_lower[n.lower()])
    return out


# Resolve names → IDs, then run.
category_id   = find_category_id(CATEGORY_NAME)
canonical     = find_asset_names(category_id, ASSETS)
series_by_asset = get_competitor_series(category_id, canonical, START_DATE, END_DATE)

# Print a labeled table: one row per asset, one column per day.
print(f"Daily Visibility Score · {START_DATE}{END_DATE} (exclusive)\n")
dates = [d for d, _ in next(iter(series_by_asset.values()))]
print(f"{'Asset':<14} " + "  ".join(f"{d:>10}" for d in dates))
for asset, points in series_by_asset.items():
    cells = "  ".join(f"{s:>10.1%}" for _, s in points)
    print(f"{asset:<14} {cells}")

Picking which competitors to plot

To avoid hardcoding asset names, fetch the top-N leaderboard first, take the top 5 by score, and feed those names into the in filter on this call.