# US Brand Signal Co-occurrence Analyzer (`zinin/us-brand-signal-cooccurrence-analyzer`) Actor

Measure deterministic co-occurrence, support, and Jaccard overlap across buyer-supplied opaque signal groups without fetching or verifying external data.

- **URL**: https://apify.com/zinin/us-brand-signal-cooccurrence-analyzer.md
- **Developed by:** [Tim Zinin](https://apify.com/zinin) (community)
- **Categories:** MCP servers, Automation, Marketing
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## US Brand Signal Co-occurrence Analyzer

US Brand Signal Co-occurrence Analyzer measures how often buyer-supplied opaque signal IDs appear together in bounded observation groups. Give it groups of IDs; it returns stable signal counts, unordered pair counts, support, Jaccard overlap, and SHA-256 digests.

The Actor only analyzes the JSON you provide. It does not fetch a website, verify a signal, identify a person or company, infer causality, or make an external truth claim.

### What you submit and receive

You submit 1 to 100 groups. Each group has a printable ASCII `groupId` and 1 to 30 unique printable ASCII `signalIds`. The Actor sorts group and signal IDs before analysis, so input order does not change the result.

You receive one Dataset report containing:

- `signalCounts`: how many submitted groups contain each signal.
- `pairRows`: stable unordered pairs with `cooccurrenceCount`, `support`, and `jaccard`.
- `groupCounts` and reconciled totals.
- SHA-256 digests for the input, groups, signal counts, pair rows, and complete result.
- A truthful `OUTPUT` receipt after one confirmed Dataset write.

For a pair, `cooccurrenceCount` is the number of groups containing both IDs. `support` is that count divided by the number of groups. `jaccard` is the count divided by the union of groups containing either ID. Values are rounded to six decimal places for stable JSON.

### Run it

1. Open **Try for free** in the Actor Console.
2. Paste the exact JSON shape shown in the Input section.
3. Start the run and read the one report row from the Dataset.
4. Read the terminal delivery receipt from `OUTPUT`.

The complete runnable prefill is also available in `examples/input.json` and `public-task.json`.

### Pricing

Pay per event: **$0.005 per run start plus $0.010 per delivered result** on the FREE tier. The result event is emitted only after one confirmed Dataset write. The Actor checks that the buyer cap covers both charges before processing.

| Tier | Discount | Start | Delivered result |
| --- | ---: | ---: | ---: |
| FREE | 0% | $0.00500 | $0.01000 |
| BRONZE | 5% | $0.00475 | $0.00950 |
| SILVER | 10% | $0.00450 | $0.00900 |
| GOLD | 15% | $0.00425 | $0.00850 |
| PLATINUM | 18% | $0.00410 | $0.00820 |
| DIAMOND | 20% | $0.00400 | $0.00800 |

Invalid input, insufficient cap, uncertain delivery, and an uncharged or multiply charged result are not reported as successful results. The Actor never retries a paid Dataset push.

### Freshness and determinism

There is no external freshness because this Actor does not fetch data and does not read the clock. Refresh the groups in your upstream system and rerun when observations change. The same groups always produce the same rows and digests, regardless of input order.

### Input

```json
{
  "schemaVersion": "1.0",
  "groups": [
    {"groupId": "observation-001", "signalIds": ["signal-a", "signal-b", "signal-c"]},
    {"groupId": "observation-002", "signalIds": ["signal-a", "signal-b"]},
    {"groupId": "observation-003", "signalIds": ["signal-a", "signal-c"]},
    {"groupId": "observation-004", "signalIds": ["signal-b", "signal-c"]}
  ]
}
```

### Output

The Dataset has one deterministic report item. `pairRows` is sorted by `signalA`, then `signalB`. A pair is stored only once with its IDs in ASCII order. `OUTPUT` contains the delivery status, receipt, and links represented by the Store output schema.

### Related public Actors

These Actors can feed or use the same buyer-owned signal workflow. This Actor does not call them.

| Actor | Use it for |
| --- | --- |
| [US Brand Signal Metrics Aggregator](https://apify.com/zinin/us-brand-signal-metrics-aggregator) | Summarize individual signal rows before comparing groups. |
| [US Brand Signal Brief Composer](https://apify.com/zinin/us-brand-signal-brief-composer) | Turn a submitted signal report into a bounded brief. |
| [US Brand Action Queue](https://apify.com/zinin/us-brand-action-queue) | Convert selected signals into next-action rows. |
| [US Brand Evidence Snapshot Diff](https://apify.com/zinin/us-brand-evidence-snapshot-diff) | Compare two buyer-supplied evidence snapshots. |
| [US Brand Offer Evidence Normalizer](https://apify.com/zinin/us-brand-offer-evidence-normalizer) | Normalize offer evidence before downstream analysis. |

### Limitations

- IDs are opaque and are not treated as names, people, companies, or verified entities.
- The maximum input is 100 groups and 30 unique IDs per group.
- Duplicate group IDs or duplicate IDs within a group fail closed.
- The report is bounded at 48 KiB. A mathematically valid input with too many distinct pairs can return `output_too_large` instead of a partial result.
- There is no network, proxy, BYOK key, LLM, clock, state, child Actor, or Dataset input.
- JSON Schema validates shape; runtime validators additionally enforce ordering, digest, and cross-field reconciliation.

### FAQ

**Does co-occurrence prove a relationship?** No. It is only a count in the groups you submitted.

**What is support?** The fraction of submitted groups containing both members of a pair.

**What is Jaccard overlap?** The pair's shared-group count divided by the groups containing either member.

**Can I submit names or URLs?** The contract accepts opaque ASCII IDs only. The Actor does not resolve identity or fetch URLs.

**Why did a valid-looking run return `output_too_large`?** The bounded report protects buyers from an incomplete or unexpectedly expensive result. Reduce the number of groups or IDs per run, or split the input upstream.

**What happens after uncertain delivery?** The Actor records a non-success terminal receipt and does not issue a second Dataset write.

Built by [zinin](https://apify.com/zinin).

# Actor input Schema

## `schemaVersion` (type: `string`):

The only supported closed contract version.

## `groups` (type: `array`):

One to 100 named groups. Each group may contain up to 30 unique opaque signal IDs.

## Actor input object example

```json
{
  "schemaVersion": "1.0",
  "groups": [
    {
      "groupId": "observation-001",
      "signalIds": [
        "signal-a",
        "signal-b",
        "signal-c"
      ]
    },
    {
      "groupId": "observation-002",
      "signalIds": [
        "signal-a",
        "signal-b"
      ]
    },
    {
      "groupId": "observation-003",
      "signalIds": [
        "signal-a",
        "signal-c"
      ]
    },
    {
      "groupId": "observation-004",
      "signalIds": [
        "signal-b",
        "signal-c"
      ]
    }
  ]
}
```

# Actor output Schema

## `OUTPUT` (type: `string`):

API link to the terminal receipt when OUTPUT was stored.

## `report` (type: `string`):

API link to the one deterministic report row after confirmed result delivery.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "schemaVersion": "1.0",
    "groups": [
        {
            "groupId": "observation-001",
            "signalIds": [
                "signal-a",
                "signal-b",
                "signal-c"
            ]
        },
        {
            "groupId": "observation-002",
            "signalIds": [
                "signal-a",
                "signal-b"
            ]
        },
        {
            "groupId": "observation-003",
            "signalIds": [
                "signal-a",
                "signal-c"
            ]
        },
        {
            "groupId": "observation-004",
            "signalIds": [
                "signal-b",
                "signal-c"
            ]
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("zinin/us-brand-signal-cooccurrence-analyzer").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "schemaVersion": "1.0",
    "groups": [
        {
            "groupId": "observation-001",
            "signalIds": [
                "signal-a",
                "signal-b",
                "signal-c",
            ],
        },
        {
            "groupId": "observation-002",
            "signalIds": [
                "signal-a",
                "signal-b",
            ],
        },
        {
            "groupId": "observation-003",
            "signalIds": [
                "signal-a",
                "signal-c",
            ],
        },
        {
            "groupId": "observation-004",
            "signalIds": [
                "signal-b",
                "signal-c",
            ],
        },
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("zinin/us-brand-signal-cooccurrence-analyzer").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "schemaVersion": "1.0",
  "groups": [
    {
      "groupId": "observation-001",
      "signalIds": [
        "signal-a",
        "signal-b",
        "signal-c"
      ]
    },
    {
      "groupId": "observation-002",
      "signalIds": [
        "signal-a",
        "signal-b"
      ]
    },
    {
      "groupId": "observation-003",
      "signalIds": [
        "signal-a",
        "signal-c"
      ]
    },
    {
      "groupId": "observation-004",
      "signalIds": [
        "signal-b",
        "signal-c"
      ]
    }
  ]
}' |
apify call zinin/us-brand-signal-cooccurrence-analyzer --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=zinin/us-brand-signal-cooccurrence-analyzer",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/LcsyaKJmOe6Z4W38M/builds/PXPMkV3G3swOkKVnC/openapi.json
