Packages
Elixir client for the Cookieless Audiences API: page-level audience segmentation and IAB categorization with no cookies and no PII.
Current section
Files
Jump to
Current section
Files
cookielessaudiences
README.md
README.md
# cookielessaudiences for Elixir
Turn a URL into an audience profile from Elixir. The library calls the Cookieless Audiences API with OTP's built-in HTTP client and decodes the answer with Jason. Nothing is tracked, and no personal data is read.
## Mix dependency
```elixir
def deps do
[{:cookielessaudiences, "~> 1.0"}]
end
```
## Usage in iex
```elixir
iex> client = CookielessAudiences.new(System.fetch_env!("COOKIELESS_KEY"))
iex> {:ok, page} = CookielessAudiences.segment(client, "https://example.com/blog")
iex> page["audience_type"]
"b2b"
iex> CookielessAudiences.labels_for(page)
["Technology & Computing", "Computing", "Computer Software"]
```
Every function returns `{:ok, map}` or `{:error, %{status: integer, message: string}}`.
## Functions
- `new(key, timeout: 120_000)`
- `segment(client, url, structured: true)`
- `categorize(client, url, confidence: true, root_fallback: false)`
- `categorize_text(client, text)`
- `vocabularies()`: public, needs no key
- `labels_for(result)`: readable names for the coded values
## Pattern match on failures
```elixir
case CookielessAudiences.segment(client, url) do
{:ok, page} -> store(url, page)
{:error, %{status: 403}} -> {:halt, :no_credits}
{:error, %{status: s}} when s in [410, 411] -> :skip
{:error, other} -> Logger.warning("segment failed: #{inspect(other)}")
end
```
The `status` is read from the JSON body. HTTP is not used to signal errors.
## Concurrent batch with Task.async_stream
```elixir
urls
|> Task.async_stream(&CookielessAudiences.segment(client, &1), max_concurrency: 8, timeout: 130_000)
|> Enum.zip(urls)
|> Enum.map(fn
{{:ok, {:ok, page}}, url} -> {url, page["audience_type"]}
{_, url} -> {url, :failed}
end)
```
Back-pressure is built in. Raise `max_concurrency` once you know your plan.
## Phoenix controller idea
```elixir
def show(conn, %{"url" => url}) do
case CookielessAudiences.segment(conn.assigns.client, url) do
{:ok, page} -> json(conn, Map.take(page, ["audience_type", "demographics", "interests"]))
{:error, e} -> conn |> put_status(502) |> json(e)
end
end
```
Cache the answer in ETS or Cachex; pages change slowly.
## Where the data is used
Teams building deal packages work from the inventory side. The [ad inventory curation](https://www.cookielessaudiences.com/features/ad-inventory-curation.php) feature page describes how coded interests turn a pile of domains into a package a buyer can understand.
## Questions
**Does it depend on Req or Finch?** No. It uses `:httpc` from OTP, so the only package is Jason.
**Which Elixir?** 1.14 or later. TLS verification uses the OTP trust store.
**License?** MIT. info@alpha-quantum.com