# Browser & Server Event Identity Batch Evidence (`h_murdock/browser-server-event-identity`) Actor

Audit supplied browser/server observation batches using exact dataset, event name and event ID. Flag reused keys, repeated sources and independently declared action-ID mismatches with evidence. Sampled absence remains unknown; no platform deduplication or live tracking claim.

- **URL**: https://apify.com/h_murdock/browser-server-event-identity.md
- **Developed by:** [Gilad Ronen](https://apify.com/h_murdock) (community)
- **Categories:** Marketing, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.25 / completed report

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Browser & Server Event Identity Batch Evidence

Compare an authorized batch of browser and server event observations after a tracking integration change or a recurring debugging export. This Actor groups exact event identities, counts repeated observations and creates a traceable report of reused keys and independently declared action conflicts. It works with supplied JSON or mapped CSV and needs no Meta credentials.

The output describes the evidence you provide. **Both sources observed with one identity does not prove that Meta deduplicated the events.** Missing counterparts in a sample remain unknown. The Actor does not send conversions, read an account, estimate attribution loss, calculate a global match rate or change an integration.

### Prepare your observations

Supply `snapshotId`, an opaque batch label, and an explicit `batchCoverage` choice: `sampled` for a partial or debugging export, or `complete` when you declare that the supplied batch covers the intended scope completely. That declaration is retained in the report and is not independently verified.

Use an `events` array. Each object is **one observed event**, with these fields:

| Field | Meaning |
| --- | --- |
| `rowId` | Unique opaque identifier for the input observation |
| `datasetId` | Exact pixel or dataset scope identifier |
| `eventName` | Exact event name; case is preserved |
| `eventId` | Exact string ID; omit, use null or an empty string when unavailable |
| `source` | Exactly `browser` or `server` |
| `actionId` | Optional opaque logical-action ID that you independently know |

Never derive `actionId` from `eventId`, timestamps, row order or a guess that two similar rows refer to the same purchase. Leave it missing when the independent relation is unknown. Use only authorized, opaque identifiers: no contact details, cookies, raw event payloads or secrets. Inputs and reports are stored in your Apify run; this is not browser-only local processing.

A short example:

```json
{
  "snapshotId": "integration-change-001",
  "batchCoverage": "sampled",
  "events": [
    {"rowId":"01","datasetId":"pixel-001","eventName":"Purchase","eventId":"0001","source":"browser","actionId":"known-action-A"},
    {"rowId":"02","datasetId":"pixel-001","eventName":"Purchase","eventId":"0002","source":"server","actionId":"known-action-A"}
  ]
}
```

These rows provide an observed ID mismatch for one independently declared action. They do not establish whether either event was accepted or attributed by a platform.

For CSV, remove the `events` field and supply `eventsCsv`. Canonical headers are `rowId,datasetId,eventName,eventId,source,actionId`. The first, second, third and fifth headers are required; ID headers may be absent. Set `eventColumns` with all six distinct mappings to use different header names. BOM, quoted commas and quoted multiline fields are supported. Duplicate headers, undeclared columns, irregular rows and duplicate row IDs are rejected. A CSV record is one observation: summary rows with browser/server count columns must be expanded into uniquely identified observations before running; counts are never guessed or expanded automatically.

### Interpret the evidence

An identity is the exact tuple of `datasetId`, `eventName` and a nonempty `eventId`. Different names and datasets remain separate. Each missing event ID stays separate. Identity rows contain source counts, original row IDs and source references, known action IDs, unknown-action counts, explicit counterpart evidence and findings.

A shared identity assigned to two distinct known action IDs is a reused-key conflict. Unknown action IDs leave reuse unresolved. Repeated browser or server observations are flagged for review; this report cannot distinguish retries, repeated collection and multiple actual sends. Action groups are scoped to dataset plus independently declared action ID, expose differing observed source ID sets or names, and retain incomplete comparisons as unknown. No timing acceptance window is applied.

### Download the report

Each completed run produces one dataset item with the full report, plus `OUTPUT` JSON, flat identity `evidence.csv`, `findings.csv` and downloadable `report.html` in the default key-value store. JSON and HTML include action groups and the complete supplied observation ledger. The HTML contains escaped data and no external scripts. CSV cells that resemble spreadsheet formulas are neutralized; original exact values remain in JSON. Logical CSV record references count data records, not physical text lines.

The limit is 2,000 observations and 4 MB total JSON input. Full JSON must remain below 8 MB and each export below 9 MB; output bounds are checked before charging. Use smaller batches for larger ledgers.

### Price and recovery

The published price is $0.25 per completed report, with platform usage included. The single billable event is `report-completed`; there is no positive startup or dataset-item charge. Invalid input or a budget below one report creates no charged report. A new run of the same input is a new report and is billable again. Resuming a saved run verifies its input and result integrity, restores missing exports and retains one dataset item and one report event. Partial exports may exist after interruption; resume the same run to complete delivery.

Use the report to prepare an evidence ledger for manual integration debugging. It does not certify tracking health, fix source instrumentation or replace a platform's own diagnostics and acceptance results.

# Actor input Schema

## `snapshotId` (type: `string`):

Opaque label for this batch; preserved exactly. No contact details.

## `batchCoverage` (type: `string`):

Choose sampled for partial or debugging exports. Complete is your declaration of full supplied-batch coverage, not independent live verification.

## `events` (type: `array`):

One object is one observed event. Required strings: rowId, datasetId, eventName, source browser/server. Optional eventId/actionId null or empty means missing. actionId must be independently known; never derive it from eventId or row order. At most 2000 rows. For CSV, remove this field.

## `eventsCsv` (type: `string`):

Use instead of events array. Unique rowId/datasetId/eventName/source headers required, eventId/actionId headers optional. One CSV record is one observed event; aggregated counts are unsupported.

## `eventColumns` (type: `object`):

Canonical mapping works without this field. All six distinct mapped header names must be supplied together when custom CSV headers are used; eventId/actionId may be absent from the actual CSV.

## Actor input object example

```json
{
  "snapshotId": "synthetic-integration-change-01",
  "batchCoverage": "sampled",
  "events": [
    {
      "rowId": "r01",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0001",
      "source": "browser",
      "actionId": "A"
    },
    {
      "rowId": "r02",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0001",
      "source": "server",
      "actionId": "A"
    },
    {
      "rowId": "r03",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0002",
      "source": "browser",
      "actionId": "B"
    },
    {
      "rowId": "r04",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": null,
      "source": "server",
      "actionId": "C"
    },
    {
      "rowId": "r05",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0004",
      "source": "server",
      "actionId": "D"
    },
    {
      "rowId": "r06",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0004",
      "source": "server",
      "actionId": "D"
    },
    {
      "rowId": "r07",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0005",
      "source": "browser",
      "actionId": "E"
    },
    {
      "rowId": "r08",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0005",
      "source": "server",
      "actionId": "F"
    },
    {
      "rowId": "r09",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0006",
      "source": "browser",
      "actionId": "G"
    },
    {
      "rowId": "r10",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0007",
      "source": "server",
      "actionId": "G"
    },
    {
      "rowId": "r11",
      "datasetId": "pixel-02",
      "eventName": "Purchase",
      "eventId": "0001",
      "source": "server",
      "actionId": "A"
    },
    {
      "rowId": "r12",
      "datasetId": "pixel-01",
      "eventName": "ViewContent",
      "eventId": "0001",
      "source": "browser",
      "actionId": "H"
    },
    {
      "rowId": "r13",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0008",
      "source": "browser",
      "actionId": null
    },
    {
      "rowId": "r14",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0008",
      "source": "server",
      "actionId": null
    },
    {
      "rowId": "r15",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0009",
      "source": "browser",
      "actionId": "I"
    },
    {
      "rowId": "r16",
      "datasetId": "pixel-01",
      "eventName": "PageView",
      "eventId": "0009",
      "source": "server",
      "actionId": "I"
    }
  ],
  "eventColumns": {
    "rowId": "rowId",
    "datasetId": "datasetId",
    "eventName": "eventName",
    "eventId": "eventId",
    "source": "source",
    "actionId": "actionId"
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

One complete report with observations, exact identities, declared actions and findings.

## `json` (type: `string`):

No description

## `evidence` (type: `string`):

No description

## `findings` (type: `string`):

No description

## `html` (type: `string`):

No description

# 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 = {
    "snapshotId": "synthetic-integration-change-01",
    "batchCoverage": "sampled",
    "events": [
        {
            "rowId": "r01",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0001",
            "source": "browser",
            "actionId": "A"
        },
        {
            "rowId": "r02",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0001",
            "source": "server",
            "actionId": "A"
        },
        {
            "rowId": "r03",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0002",
            "source": "browser",
            "actionId": "B"
        },
        {
            "rowId": "r04",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": null,
            "source": "server",
            "actionId": "C"
        },
        {
            "rowId": "r05",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0004",
            "source": "server",
            "actionId": "D"
        },
        {
            "rowId": "r06",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0004",
            "source": "server",
            "actionId": "D"
        },
        {
            "rowId": "r07",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0005",
            "source": "browser",
            "actionId": "E"
        },
        {
            "rowId": "r08",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0005",
            "source": "server",
            "actionId": "F"
        },
        {
            "rowId": "r09",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0006",
            "source": "browser",
            "actionId": "G"
        },
        {
            "rowId": "r10",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0007",
            "source": "server",
            "actionId": "G"
        },
        {
            "rowId": "r11",
            "datasetId": "pixel-02",
            "eventName": "Purchase",
            "eventId": "0001",
            "source": "server",
            "actionId": "A"
        },
        {
            "rowId": "r12",
            "datasetId": "pixel-01",
            "eventName": "ViewContent",
            "eventId": "0001",
            "source": "browser",
            "actionId": "H"
        },
        {
            "rowId": "r13",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0008",
            "source": "browser",
            "actionId": null
        },
        {
            "rowId": "r14",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0008",
            "source": "server",
            "actionId": null
        },
        {
            "rowId": "r15",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0009",
            "source": "browser",
            "actionId": "I"
        },
        {
            "rowId": "r16",
            "datasetId": "pixel-01",
            "eventName": "PageView",
            "eventId": "0009",
            "source": "server",
            "actionId": "I"
        }
    ],
    "eventsCsv": "",
    "eventColumns": {
        "rowId": "rowId",
        "datasetId": "datasetId",
        "eventName": "eventName",
        "eventId": "eventId",
        "source": "source",
        "actionId": "actionId"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("h_murdock/browser-server-event-identity").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 = {
    "snapshotId": "synthetic-integration-change-01",
    "batchCoverage": "sampled",
    "events": [
        {
            "rowId": "r01",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0001",
            "source": "browser",
            "actionId": "A",
        },
        {
            "rowId": "r02",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0001",
            "source": "server",
            "actionId": "A",
        },
        {
            "rowId": "r03",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0002",
            "source": "browser",
            "actionId": "B",
        },
        {
            "rowId": "r04",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": None,
            "source": "server",
            "actionId": "C",
        },
        {
            "rowId": "r05",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0004",
            "source": "server",
            "actionId": "D",
        },
        {
            "rowId": "r06",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0004",
            "source": "server",
            "actionId": "D",
        },
        {
            "rowId": "r07",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0005",
            "source": "browser",
            "actionId": "E",
        },
        {
            "rowId": "r08",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0005",
            "source": "server",
            "actionId": "F",
        },
        {
            "rowId": "r09",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0006",
            "source": "browser",
            "actionId": "G",
        },
        {
            "rowId": "r10",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0007",
            "source": "server",
            "actionId": "G",
        },
        {
            "rowId": "r11",
            "datasetId": "pixel-02",
            "eventName": "Purchase",
            "eventId": "0001",
            "source": "server",
            "actionId": "A",
        },
        {
            "rowId": "r12",
            "datasetId": "pixel-01",
            "eventName": "ViewContent",
            "eventId": "0001",
            "source": "browser",
            "actionId": "H",
        },
        {
            "rowId": "r13",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0008",
            "source": "browser",
            "actionId": None,
        },
        {
            "rowId": "r14",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0008",
            "source": "server",
            "actionId": None,
        },
        {
            "rowId": "r15",
            "datasetId": "pixel-01",
            "eventName": "Purchase",
            "eventId": "0009",
            "source": "browser",
            "actionId": "I",
        },
        {
            "rowId": "r16",
            "datasetId": "pixel-01",
            "eventName": "PageView",
            "eventId": "0009",
            "source": "server",
            "actionId": "I",
        },
    ],
    "eventsCsv": "",
    "eventColumns": {
        "rowId": "rowId",
        "datasetId": "datasetId",
        "eventName": "eventName",
        "eventId": "eventId",
        "source": "source",
        "actionId": "actionId",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("h_murdock/browser-server-event-identity").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "snapshotId": "synthetic-integration-change-01",
  "batchCoverage": "sampled",
  "events": [
    {
      "rowId": "r01",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0001",
      "source": "browser",
      "actionId": "A"
    },
    {
      "rowId": "r02",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0001",
      "source": "server",
      "actionId": "A"
    },
    {
      "rowId": "r03",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0002",
      "source": "browser",
      "actionId": "B"
    },
    {
      "rowId": "r04",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": null,
      "source": "server",
      "actionId": "C"
    },
    {
      "rowId": "r05",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0004",
      "source": "server",
      "actionId": "D"
    },
    {
      "rowId": "r06",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0004",
      "source": "server",
      "actionId": "D"
    },
    {
      "rowId": "r07",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0005",
      "source": "browser",
      "actionId": "E"
    },
    {
      "rowId": "r08",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0005",
      "source": "server",
      "actionId": "F"
    },
    {
      "rowId": "r09",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0006",
      "source": "browser",
      "actionId": "G"
    },
    {
      "rowId": "r10",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0007",
      "source": "server",
      "actionId": "G"
    },
    {
      "rowId": "r11",
      "datasetId": "pixel-02",
      "eventName": "Purchase",
      "eventId": "0001",
      "source": "server",
      "actionId": "A"
    },
    {
      "rowId": "r12",
      "datasetId": "pixel-01",
      "eventName": "ViewContent",
      "eventId": "0001",
      "source": "browser",
      "actionId": "H"
    },
    {
      "rowId": "r13",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0008",
      "source": "browser",
      "actionId": null
    },
    {
      "rowId": "r14",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0008",
      "source": "server",
      "actionId": null
    },
    {
      "rowId": "r15",
      "datasetId": "pixel-01",
      "eventName": "Purchase",
      "eventId": "0009",
      "source": "browser",
      "actionId": "I"
    },
    {
      "rowId": "r16",
      "datasetId": "pixel-01",
      "eventName": "PageView",
      "eventId": "0009",
      "source": "server",
      "actionId": "I"
    }
  ],
  "eventsCsv": "",
  "eventColumns": {
    "rowId": "rowId",
    "datasetId": "datasetId",
    "eventName": "eventName",
    "eventId": "eventId",
    "source": "source",
    "actionId": "actionId"
  }
}' |
apify call h_murdock/browser-server-event-identity --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,h_murdock/browser-server-event-identity"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

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