# Ad Budget Signals — Do These Domains Run Ads? (`tactful_anvil/ad-budget-signals`) Actor

Enrich any domain list with advertising activity: runs ads yes/no, networks, creative count, first/last seen, formats, verified advertiser + a 0-100 budget signal score. One flat CRM-ready row per domain. Qualify leads by marketing budget. HTTP-only, no API keys. $3.20/1,000 domains.

- **URL**: https://apify.com/tactful\_anvil/ad-budget-signals.md
- **Developed by:** [Mr Zack](https://apify.com/tactful_anvil) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.20 / 1,000 domain checkeds

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?

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

## Ad Budget Signals — do these domains run ads? $3.20/1,000 domains

Paste a list of company domains (from your CRM, a lead list, or another scraper) and get back **one flat row per domain** answering the question every seller and marketer asks: **does this company spend money on advertising?**

Checked against two public sources over plain HTTP — the **Google Ads Transparency Center** and the **LinkedIn Ad Library**. No API keys, no login, no browser, no proxies. A company that runs ads has a marketing budget; a company with a marketing budget can buy what you sell.

**$3.20 per 1,000 domains checked + $0.001 per start.** "No ads found" is a real answer and is charged; a domain where both sources fail to respond is never charged.

### Who uses this

- **Sales & SDR teams** — prioritize leads that already spend on ads: they have budget and buy tools. Sort your CRM by `budgetSignalScore`.
- **Marketing agencies** — prospects already buying ads are the easiest upsell ("we'll make your existing spend work harder"). Filter for `advertises = true`.
- **AI sales agents** — one call, flat schema, predictable cost: qualify a lead list without any human clicking through two ad libraries per company.
- **Investors & analysts** — quick read on which companies in a space are in growth mode.

### What you get per domain

| Field | Example | Notes |
|---|---|---|
| `domain` | `hubspot.com` | cleaned input |
| `advertises` | `true` | any ads found on any network |
| `networks` | `google,linkedin` | where |
| `budgetSignalScore` | `85` | 0–100, formula below |
| `googleAdCount` (+`Capped`) | `60` | creatives found (scan-capped) |
| `googleAdvertiserName` / `googleAdvertiserId` | `HubSpot, Inc.` | resolved verified advertiser |
| `googleTextAds` / `googleImageAds` / `googleVideoAds` | | format mix |
| `googleFirstSeen` / `googleLastSeen` | ISO dates | ad activity window |
| `googleDaysSinceLastAd` | `2` | freshness |
| `linkedinAdCount` | `24` | ads from matching advertisers |
| `linkedinMatchedAdvertisers` | `HubSpot` | who's actually advertising |
| `googleLibraryUrl` / `linkedinLibraryUrl` | | one-click verification links |
| `signalChanged` | `true` | monitor mode: activity changed since last run |
| `errors`, `checkedAt` | | transparency |

Every field is always present (nullable, never missing). Rows import straight into Sheets, HubSpot or Salesforce.

### The score (transparent, no magic)

`budgetSignalScore` 0–100: +35 Google ads active in the last 30 days, +15 active in the last 7 days, +20 LinkedIn ads present, +10 both networks, +10 ≥10 Google creatives, +5 ≥50 creatives, +5 video ads present (video = bigger production budget).

### Input

```json
{
  "domains": ["hubspot.com", "temu.com", "smallshop.example"],
  "networks": ["google", "linkedin"],
  "onlyChanges": false
}
```

- **domains** — your list; URLs are cleaned automatically.
- **region** — optionally restrict Google results to one country (`US`, `DE`, `ID`…).
- **maxAdsScanned** — scan depth per network (affects count precision, not price).
- **linkedinNameMatch** — only count LinkedIn ads whose advertiser matches the domain's brand (default on).
- **onlyChanges** — monitor mode, see below.

### Monitor mode — re-qualify your pipeline for cents

Set `"onlyChanges": true` and schedule the run. The Actor remembers each domain's signal fingerprint; on later runs, **unchanged domains are skipped and never charged**. You only pay when a lead starts advertising, stops, or scales — exactly the moments a seller wants to know about.

### How to schedule this Actor (recommended)

1. Open the Actor → **Try for free**, paste your domain list.
2. Save as a task → **Schedules** → weekly (`0 7 * * 1`) with `"onlyChanges": true`.
3. Add an integration (Google Sheets, Slack, HubSpot webhook) — new-signal rows land where your pipeline lives.

Re-checking 1,000 CRM domains weekly costs at most $3.20, and usually far less in monitor mode.

### For AI agents & MCP

Built to be called by AI agents via the [Apify MCP server](https://apify.com/apify/actors-mcp-server) or API:

- Minimal input that just works: `{"domains": ["<domain>"]}`.
- Predictable cost: exactly `$0.0032 × domains` + `$0.001` per run.
- Stable flat schema; `domain` is the join key back to your CRM.

### The full lead-qualification chain

1. **Qualify budget** — this Actor: who's spending?
2. **[Contact Details Scraper](https://apify.com/tactful_anvil/contact-details-scraper)** — pull emails, phones and socials from the qualified domains.
3. **[Bulk Email Verifier](https://apify.com/tactful_anvil/bulk-email-verifier)** — verify before outreach.

Want the actual creatives, not just the signal? **[Google Ads Transparency Scraper](https://apify.com/tactful_anvil/google-ads-transparency-scraper)** ($0.64/1k ads) and **[Brand Ads Spy — Google + LinkedIn](https://apify.com/tactful_anvil/brand-ads-cross-network-spy)** ($1.20/1k ads) return every ad row.

### Fair use & data source

Only public data from the Google Ads Transparency Center and the public LinkedIn Ad Library (both published for transparency purposes). Reasonable rate limits. No login, no personal data.

# Actor input Schema

## `domains` (type: `array`):

Company domains from your lead list or CRM, e.g. \["hubspot.com", "temu.com"]. URLs are cleaned automatically.

## `networks` (type: `array`):

Subset of: google, linkedin. Default both.

## `region` (type: `string`):

ISO alpha-2 country code (US, GB, DE, ID…) filtering where Google ads were shown, or "anywhere".

## `maxAdsScanned` (type: `integer`):

Scan depth for counting creatives. Affects count precision only — the price per domain stays the same.

## `linkedinNameMatch` (type: `boolean`):

Keeps only LinkedIn ads whose advertiser name matches the domain brand token. Turn off to count every ad the keyword search returns.

## `onlyChanges` (type: `boolean`):

Remembers each domain signal fingerprint. On later runs, unchanged domains are skipped and never charged — schedule weekly and only pay when a lead ad activity changes.

## Actor input object example

```json
{
  "domains": [
    "hubspot.com",
    "temu.com",
    "thisdomaindoesnotexist12345.com"
  ],
  "networks": [
    "google",
    "linkedin"
  ],
  "region": "anywhere",
  "maxAdsScanned": 60,
  "linkedinNameMatch": true,
  "onlyChanges": false
}
```

# Actor output Schema

## `signals` (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 = {
    "domains": [
        "hubspot.com",
        "temu.com",
        "thisdomaindoesnotexist12345.com"
    ],
    "networks": [
        "google",
        "linkedin"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("tactful_anvil/ad-budget-signals").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 = {
    "domains": [
        "hubspot.com",
        "temu.com",
        "thisdomaindoesnotexist12345.com",
    ],
    "networks": [
        "google",
        "linkedin",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("tactful_anvil/ad-budget-signals").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 '{
  "domains": [
    "hubspot.com",
    "temu.com",
    "thisdomaindoesnotexist12345.com"
  ],
  "networks": [
    "google",
    "linkedin"
  ]
}' |
apify call tactful_anvil/ad-budget-signals --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tactful_anvil/ad-budget-signals"
        }
    }
}

```

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/pHY72BQ9GWrWmenH8/builds/GwXm1LT4oAMOlc6Jg/openapi.json
