# Campaign UTM Auditor (`danielmichalek/campaign-naming-utm-validator`) Actor

Audit campaign destination URLs for missing UTM parameters, conflicting tags and naming errors. Export a prioritized report before ads go live. Ready to check your campaign links?

- **URL**: https://apify.com/danielmichalek/campaign-naming-utm-validator.md
- **Developed by:** [Daniel Michałek](https://apify.com/danielmichalek) (community)
- **Categories:** Marketing
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$20.00 / 1,000 campaign audit reports

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

## Campaign UTM Auditor

Audit exported destination links before launching or handing over a campaign. One run checks up to 500 URLs and produces a prioritized JSON and CSV report. This deterministic audit requires no AI subscription, ad-account login, proxy or destination crawl.

### What it does

Find missing source, medium and campaign tags; uppercase parameter names; duplicate or conflicting values; whitespace; naming mismatches; UTM tags hidden in fragments; unresolved ad-platform macros; and attribution groups split by letter case. Supply exact source and medium allowlists and choose a campaign naming convention.

Rows are marked PASS, WARN or ERROR. Findings contain codes, severities, duplicate-row references and suggested URLs where a mechanical suggestion is possible. Click IDs, product variants, non-UTM query parameters and normal fragments are retained. The Actor does not modify advertisements or request destination pages.

### Input

Required field links accepts 1 to 500 URL strings or objects containing url and optional id and campaignName. Each URL is limited to 8192 characters; the combined URL text to 500000 characters; metadata strings to 200. Oversized or malformed batches fail instead of silently truncating campaign exports. Individual invalid URLs become ERROR rows without echoing their raw text.

campaignConvention is lowercase-dash by default; alternatives are snake_case and any. allowedSources and allowedMediums are optional arrays of up to 30 exact, case-sensitive values. normalizeSourceMedium defaults to false; opting in changes source and medium values only in suggestions. Campaign values are not lowercased automatically.

### Output

One dataset item contains summary counts, attribution groups, rows and recommendations. Each row includes its identifiers, sanitized destination, source, medium, campaign, status, findings and nullable suggestedUrl. Key-value records AUDIT (JSON), AUDIT_CSV (UTF-8 CSV with BOM) and REPORT (Markdown) support client handover. Spreadsheet formula prefixes are escaped in CSV.

### Pricing and cost control

The listing price is $0.02 per completed audit-report event, covering the entire batch of up to 500 URLs, not each URL. There is one report event per successful run; invalid batches produce no report event. Apify may display platform or startup usage separately according to the active listing and plan. Set the run charge limit to control event charges. There is no paid model, proxy or external service.

### Limitations and fair use

PASS describes syntax and configured rules, not proven analytics delivery, destination availability, ad approval or campaign performance. Custom channel grouping can be valid; warnings request review. Macros require verification in their originating ad platform. Suggested URLs are drafts: review before replacing historical links, signed URLs, SPA routes or click tracking. The Actor does not remove click IDs or infer missing attribution values.

Known secret-like query keys, URL credentials and detected email addresses are masked in reports. The local source also recognizes sensitive parameter names in URL fragments and encoded query keys. A matching fragment is withheld in full, marked FRAGMENT_WITHHELD and receives no suggested URL. Ordinary fragments remain unchanged without any claim that they are safe. This is not comprehensive anonymization: recognition uses a fixed key list and bounded decoding. Avoid passwords, customer data and private tokens in input. Apify still stores run input independently of output masking.

### Example

Supply https://shop.example/p?utm_source=google\&utm_medium=cpc\&utm_campaign=winter-sale for a PASS example. An uppercase UTM_Source receives a parameter-name error. A link containing only utm_source reports missing medium and campaign. See examples/input.json and examples/output.json for an executed batch. Example domains are synthetic; the actual SDK run, files and billing event are independently verified during release.

# Actor input Schema

## `links` (type: `array`):

1 to 500 HTTP/HTTPS URLs as strings or objects with url and optional id and campaignName. URLs are analyzed locally and never fetched.

## `campaignConvention` (type: `string`):

Check utm_campaign against this static rule without automatically renaming it.

## `allowedSources` (type: `array`):

Optional exact, case-sensitive allowlist. Up to30 names; empty disables the rule.

## `allowedMediums` (type: `array`):

Optional exact, case-sensitive allowlist. Otherwise custom media receive a review warning.

## `normalizeSourceMedium` (type: `boolean`):

Opt in to lowercase source and medium in draft URL suggestions. Existing campaign and click ID values remain unchanged.

## `maxItems` (type: `integer`):

One complete report per run, covering all supplied links; the batch may contain up to500 URLs.

## Actor input object example

```json
{
  "links": [
    {
      "id": "ad-1",
      "url": "https://shop.example/product?utm_source=google&utm_medium=cpc&utm_campaign=winter-sale"
    }
  ],
  "campaignConvention": "lowercase-dash",
  "allowedSources": [],
  "allowedMediums": [],
  "normalizeSourceMedium": false,
  "maxItems": 1
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `csv` (type: `string`):

No description

## `audit` (type: `string`):

No description

## `report` (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 = {
    "links": [
        {
            "id": "ad-1",
            "url": "https://shop.example/product?utm_source=google&utm_medium=cpc&utm_campaign=winter-sale"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("danielmichalek/campaign-naming-utm-validator").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 = { "links": [{
            "id": "ad-1",
            "url": "https://shop.example/product?utm_source=google&utm_medium=cpc&utm_campaign=winter-sale",
        }] }

# Run the Actor and wait for it to finish
run = client.actor("danielmichalek/campaign-naming-utm-validator").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 '{
  "links": [
    {
      "id": "ad-1",
      "url": "https://shop.example/product?utm_source=google&utm_medium=cpc&utm_campaign=winter-sale"
    }
  ]
}' |
apify call danielmichalek/campaign-naming-utm-validator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,danielmichalek/campaign-naming-utm-validator"
        }
    }
}
```

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/Wl5CwTzNGiXRZwin1/builds/k0M8UzAnfbd5kEveI/openapi.json
