# AI Icebreaker Generator - Cold-Email Opening Lines (`santamaria-automations/ai-icebreaker`) Actor

Generate one personalized cold-outreach opening line per Google Maps place record using a BYO LLM key chain (Gemini, Groq, OpenRouter). Base mode uses only fields already on the place record (zero fetch). Enriched mode also fetches the homepage and folds a summary into the prompt. Pay-per-result.

- **URL**: https://apify.com/santamaria-automations/ai-icebreaker.md
- **Developed by:** [NanoScrape](https://apify.com/santamaria-automations) (community)
- **Categories:** Lead generation, AI, Automation
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 result (base)s

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/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

## AI Icebreaker Generator

Turn a batch of Google Maps place records into one hyper-personalized cold-outreach opening line per business. Bring your own LLM key (Gemini has a generous free tier). Two modes: base uses only fields already present on the place, enriched also fetches the homepage and folds a summary into the prompt.

Feed it the output of the [Google Maps Scraper](https://apify.com/santamaria-automations/google-maps-scraper) and get one ready-to-send opener per business.

### What It Does

Given a Google Maps place record, the actor asks an LLM to write ONE sentence that:

- Is at most 200 characters
- References something specific about the business (rating, category + city, tenure, description, homepage detail)
- Matches the requested `tone` (friendly, professional, casual, direct)
- Is grounded in the input data. Never a generic template, never invented facts.
- Falls back to an empty string when the record has too little signal (no name, or missing category AND reviews AND description)

### Modes

#### Base (default, zero-fetch)

Uses only fields already on the place record:

- `title` / `name`
- `category`, `categories`
- `city`, `country` (from `complete_address`)
- `rating` / `review_rating`, `review_count`
- `description`
- `phone`, `website` (reference only, not fetched)

#### Enriched (opt-in)

Set `enableEnriched: true`. In addition to base mode, the actor fetches the business's homepage, condenses it into a ~1000 character markdown summary (headings + tagline + prose paragraphs), and appends it to the LLM prompt. Falls back silently to base mode when the site returns non-200, redirects strangely, or trips an anti-bot challenge.

### Input

Two shapes are accepted, and you can mix them in one run.

Flat places list (natural shape, just pipe the google-maps-scraper output):

```json
{
  "places": [
    {
      "place_id": "ChIJN1t_tDeuEmsRUsoyG83frY4",
      "title": "Example Coffee House",
      "category": "Coffee shop",
      "website": "https://example-coffee.example",
      "rating": 4.8,
      "review_count": 1240,
      "complete_address": { "city": "Berlin", "country": "Germany" }
    }
  ],
  "tone": "friendly",
  "outputLanguage": "en",
  "geminiApiKey": "AIza..."
}
```

Companies shape (with a `company_id` passthrough for join-back to your CRM):

```json
{
  "companies": [
    { "company_id": "acme-42", "place": { "place_id": "ChIJ...", "title": "Example Company Ltd." } }
  ],
  "tone": "professional",
  "geminiApiKey": "AIza..."
}
```

#### Input parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `places` | array | (none) | Flat places array — pipe directly from Google Maps Scraper output. |
| `companies` | array | (none) | Wrapped shape with `company_id` per row for CRM join-back. Mix with `places` in the same run if useful. |
| `tone` | string | `"friendly"` | Voice of the generated line: `friendly` (warm and professional), `professional` (buttoned-up), `casual` (chatty), `direct` (punchy, to the point). |
| `focus` | string | (none) | Optional free-text guidance passed to the LLM alongside the place record. Steers every line toward your specific outreach angle. Example: `"Focus on their photo count and their newest reviews"`, or `"Mention that we specialize in local SEO for care homes"`. |
| `enableEnriched` | boolean | `false` | When true, fetches the business's homepage, condenses it into a short summary, and folds it into the icebreaker prompt. Sharper lines, slightly higher cost. Falls back silently to base mode on 404 / anti-bot. |
| `outputLanguage` | string | `"en"` | ISO 639-1 language code (`en`, `de`, `fr`, etc.) or `auto` to detect from the website. |
| `llmProvider` | string | `"gemini"` | Primary LLM: `gemini`, `groq`, or `openrouter`. |
| `fallbackProvider` | string | (none) | Fallback on auth/quota errors from the primary. |
| `fallback2Provider` | string | (none) | Second-line fallback. |
| `geminiApiKey` / `groqApiKey` / `openrouterApiKey` | string | (none) | At least one is required — the actor never makes LLM calls on your behalf, keys go straight to your provider account. |

#### The `focus` field — usage tips

Two shapes work well:

1. **Content-specific**: point the model at a signal you care about — `"Focus on their photos and their newest reviews"`, `"Mention their recent hiring signal"`, `"Reference their tech stack"`.
2. **Angle-specific**: tell the model what YOU sell — `"Mention that we specialize in local SEO for care homes"`, `"We are a payments processor pitching lower fees to independent restaurants"`, `"We build websites for solo dentists"`.

Leave it empty when you want the model to pick the sharpest angle itself. `focus` is a steering signal, not a directive — if the place record has no photos and you asked to reference photo count, the line will pivot to another salient signal rather than fabricating one.

### LLM Configuration

You must supply at least one LLM key. All three providers are supported:

| Provider | Free tier | Get a key |
|----------|-----------|-----------|
| Gemini | Yes (generous) | https://aistudio.google.com/app/apikey |
| Groq | Yes | https://console.groq.com/keys |
| OpenRouter | Pay-as-you-go, cheap | https://openrouter.ai/keys |

Set `llmProvider` to pick the primary, `fallbackProvider` and `fallback2Provider` for the chain. Same-provider transient errors (5xx, timeouts) get one retry; auth/quota errors fall through to the next provider.

### Output

One row per input place:

```json
{
  "company_id": "acme-42",
  "place_id": "ChIJN1t_tDeuEmsRUsoyG83frY4",
  "name": "Example Coffee House",
  "icebreaker_line": "Noticed you are running one of the highest-rated (4.8 stars, 1,240 reviews) coffee shops in Berlin. Curious how you keep that streak going.",
  "icebreaker_enriched": false,
  "llm_provider": "gemini",
  "llm_model": "gemini-2.0-flash",
  "llm_tokens_input": 340,
  "llm_tokens_output": 45,
  "generated_at": "2026-07-17T10:30:00Z"
}
```

`icebreaker_line` is an empty string when the record had too little signal to produce a specific line. The actor never invents facts to fill the gap.

### How To Use It

1. Run [Google Maps Scraper](https://apify.com/santamaria-automations/google-maps-scraper) to collect places for a niche and city.
2. Feed the dataset into this actor as `places` (or wrap each in `companies` for join-back).
3. Pick a tone, set your Gemini key, and (optionally) turn on enriched mode.
4. Drop the output into your outbound sequencer.

### Pricing

Pay-per-result via Apify Pay-Per-Event billing:

| Event | Price | Description |
|-------|-------|-------------|
| Actor start | $0.001 | Charged once per run |
| Icebreaker generated (base) | $0.003 | Charged per row in base mode |
| Icebreaker generated (enriched) | $0.005 | Charged per row when enriched mode succeeded |

Generating 1,000 lines in base mode costs about $3. Empty input rows and rows the model refused to write for (insufficient signal) are still counted as a result. LLM API usage is billed by your provider directly, not by this actor.

### Related Actors

Discovery:

- [Google Maps Scraper](https://apify.com/santamaria-automations/google-maps-scraper) - collect places in bulk

Enrichment:

- [GBP Completeness Audit](https://apify.com/santamaria-automations/gbp-completeness-audit) - score Google Business Profiles for lead prioritization
- [Website Email Scraper](https://apify.com/santamaria-automations/website-email-scraper) - pull emails and phones from company sites
- [Website Contact Extractor](https://apify.com/santamaria-automations/website-contact-extractor) - LLM-powered people extraction

### Notes

- Empty input is free. No `enrichment-start` is billed unless there is at least one valid place.
- The proxy configuration is only used by enriched mode's homepage fetch.
- Language: set `outputLanguage: "auto"` to have the model match the business's country language.

### Issues & Feature Requests

If the model keeps refusing lines for a class of business, or if you would like a new tone, open an issue on the actor's Issues tab and we will take a look.

# Actor input Schema

## `places` (type: `array`):

Array of Google Maps place records. Each element is a full place object as emitted by the google-maps-scraper actor (with `title`, `category`, `categories`, `website`, `phone`, `rating`, `review_count`, `description`, `complete_address`, etc.).

## `companies` (type: `array`):

Alternative to `places`. Each entry carries a company\_id (echoed on the output row) plus the place record.

## `tone` (type: `string`):

Voice of the generated line. `friendly` is warm and professional (default), `professional` is buttoned-up, `casual` is chatty, `direct` is punchy and to-the-point.

## `focus` (type: `string`):

Optional free-text guidance passed to the LLM alongside the place record. Steers every line toward your specific outreach angle. Example: 'Focus on their photo count and their newest reviews', or 'Mention that we specialize in local SEO for care homes'.

## `enableEnriched` (type: `boolean`):

When true, the actor fetches each business's homepage, condenses it into a short summary, and folds it into the icebreaker prompt. Costs slightly more per row but produces sharper lines. Falls back silently to base mode when the site 404s or hits an anti-bot challenge.

## `llmProvider` (type: `string`):

Primary AI provider. Gemini Flash is fastest and has a generous free tier.

## `fallbackProvider` (type: `string`):

Second-level fallback if the primary provider fails (rate limit, auth error, etc).

## `fallback2Provider` (type: `string`):

Third-level fallback if both primary and first fallback fail.

## `llmModel` (type: `string`):

Override the default model. Defaults: Gemini -> gemini-2.0-flash, Groq -> llama-3.3-70b-versatile, OpenRouter -> google/gemini-2.0-flash-001. If your OpenRouter key does not have access to the default paid Gemini model, try a free model like meta-llama/llama-3.1-8b-instruct.

## `geminiApiKey` (type: `string`):

Google Gemini Flash. Best quality/cost ratio, generous free tier. Get a key at https://aistudio.google.com/app/apikey

## `groqApiKey` (type: `string`):

Groq. Ultra-fast inference. Get a key at https://console.groq.com/keys

## `openrouterApiKey` (type: `string`):

OpenRouter. Access to 100+ models. Get a key at https://openrouter.ai/keys

## `outputLanguage` (type: `string`):

Language for the generated icebreaker line. Uses standard ISO 639-1 codes. Pass any ISO 639-1 language code: en, de, fr, ja, es, pt, it, ko, zh-CN, ar, nl, pl, sv, da, fi, no, cs, hu, ro, el, tr, th, vi, id, and more. Set to `auto` to match the business's country/language.

## `proxyConfiguration` (type: `object`):

Only used when enriched mode is enabled (for the homepage fetch). Apify proxy works for most sites.

## Actor input object example

```json
{
  "places": [
    {
      "place_id": "ChIJN1t_tDeuEmsRUsoyG83frY4",
      "title": "Example Coffee House",
      "category": "Coffee shop",
      "categories": [
        "Coffee shop",
        "Cafe"
      ],
      "website": "https://example-coffee.example",
      "phone": "+49 30 12345678",
      "rating": 4.8,
      "review_count": 1240,
      "description": "Specialty coffee roastery, direct-trade beans, natural wines and weekend brunch.",
      "complete_address": {
        "city": "Berlin",
        "country": "Germany",
        "borough": "Sample District"
      }
    },
    {
      "place_id": "ChIJcareHomeSAMPLE12345",
      "title": "Sample Care Foundation",
      "category": "Nursing home",
      "categories": [
        "Nursing home",
        "Senior care service"
      ],
      "phone": "+49 7531 200000",
      "rating": 4.4,
      "review_count": 87,
      "description": "Sample Care Foundation has been caring for seniors for over 20 years across three residential campuses.",
      "complete_address": {
        "city": "Sampletown",
        "country": "Germany"
      }
    },
    {
      "place_id": "ChIJsculptureStudio77",
      "title": "Example Art Studio",
      "category": "Sculptor",
      "website": "https://example-studio.example",
      "rating": 5,
      "review_count": 12,
      "complete_address": {
        "city": "Berlin",
        "country": "Germany"
      }
    }
  ],
  "tone": "friendly",
  "enableEnriched": false,
  "llmProvider": "gemini",
  "outputLanguage": "en",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `icebreakers` (type: `string`):

Dataset of generated icebreaker rows

# 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 = {
    "places": [
        {
            "place_id": "ChIJN1t_tDeuEmsRUsoyG83frY4",
            "title": "Example Coffee House",
            "category": "Coffee shop",
            "categories": [
                "Coffee shop",
                "Cafe"
            ],
            "website": "https://example-coffee.example",
            "phone": "+49 30 12345678",
            "rating": 4.8,
            "review_count": 1240,
            "description": "Specialty coffee roastery, direct-trade beans, natural wines and weekend brunch.",
            "complete_address": {
                "city": "Berlin",
                "country": "Germany",
                "borough": "Sample District"
            }
        },
        {
            "place_id": "ChIJcareHomeSAMPLE12345",
            "title": "Sample Care Foundation",
            "category": "Nursing home",
            "categories": [
                "Nursing home",
                "Senior care service"
            ],
            "phone": "+49 7531 200000",
            "rating": 4.4,
            "review_count": 87,
            "description": "Sample Care Foundation has been caring for seniors for over 20 years across three residential campuses.",
            "complete_address": {
                "city": "Sampletown",
                "country": "Germany"
            }
        },
        {
            "place_id": "ChIJsculptureStudio77",
            "title": "Example Art Studio",
            "category": "Sculptor",
            "website": "https://example-studio.example",
            "rating": 5,
            "review_count": 12,
            "complete_address": {
                "city": "Berlin",
                "country": "Germany"
            }
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("santamaria-automations/ai-icebreaker").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 = { "places": [
        {
            "place_id": "ChIJN1t_tDeuEmsRUsoyG83frY4",
            "title": "Example Coffee House",
            "category": "Coffee shop",
            "categories": [
                "Coffee shop",
                "Cafe",
            ],
            "website": "https://example-coffee.example",
            "phone": "+49 30 12345678",
            "rating": 4.8,
            "review_count": 1240,
            "description": "Specialty coffee roastery, direct-trade beans, natural wines and weekend brunch.",
            "complete_address": {
                "city": "Berlin",
                "country": "Germany",
                "borough": "Sample District",
            },
        },
        {
            "place_id": "ChIJcareHomeSAMPLE12345",
            "title": "Sample Care Foundation",
            "category": "Nursing home",
            "categories": [
                "Nursing home",
                "Senior care service",
            ],
            "phone": "+49 7531 200000",
            "rating": 4.4,
            "review_count": 87,
            "description": "Sample Care Foundation has been caring for seniors for over 20 years across three residential campuses.",
            "complete_address": {
                "city": "Sampletown",
                "country": "Germany",
            },
        },
        {
            "place_id": "ChIJsculptureStudio77",
            "title": "Example Art Studio",
            "category": "Sculptor",
            "website": "https://example-studio.example",
            "rating": 5,
            "review_count": 12,
            "complete_address": {
                "city": "Berlin",
                "country": "Germany",
            },
        },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("santamaria-automations/ai-icebreaker").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 '{
  "places": [
    {
      "place_id": "ChIJN1t_tDeuEmsRUsoyG83frY4",
      "title": "Example Coffee House",
      "category": "Coffee shop",
      "categories": [
        "Coffee shop",
        "Cafe"
      ],
      "website": "https://example-coffee.example",
      "phone": "+49 30 12345678",
      "rating": 4.8,
      "review_count": 1240,
      "description": "Specialty coffee roastery, direct-trade beans, natural wines and weekend brunch.",
      "complete_address": {
        "city": "Berlin",
        "country": "Germany",
        "borough": "Sample District"
      }
    },
    {
      "place_id": "ChIJcareHomeSAMPLE12345",
      "title": "Sample Care Foundation",
      "category": "Nursing home",
      "categories": [
        "Nursing home",
        "Senior care service"
      ],
      "phone": "+49 7531 200000",
      "rating": 4.4,
      "review_count": 87,
      "description": "Sample Care Foundation has been caring for seniors for over 20 years across three residential campuses.",
      "complete_address": {
        "city": "Sampletown",
        "country": "Germany"
      }
    },
    {
      "place_id": "ChIJsculptureStudio77",
      "title": "Example Art Studio",
      "category": "Sculptor",
      "website": "https://example-studio.example",
      "rating": 5,
      "review_count": 12,
      "complete_address": {
        "city": "Berlin",
        "country": "Germany"
      }
    }
  ]
}' |
apify call santamaria-automations/ai-icebreaker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=santamaria-automations/ai-icebreaker",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/44bvXlco2wj95j3gQ/builds/SKFkvml3da6XTiCkI/openapi.json
