# SaaS Competitor Battlecard Generator (`city-in-the-sky/saas-competitor-battlecard-generator`) Actor

Generate AI competitor battlecards, pricing signals, differentiation angles, and sales talk tracks from public SaaS websites.

- **URL**: https://apify.com/city-in-the-sky/saas-competitor-battlecard-generator.md
- **Developed by:** [city in the sky](https://apify.com/city-in-the-sky) (community)
- **Categories:** AI, Marketing, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## SaaS Competitor Battlecard Generator

Built by `city in the sky`.

This Apify Actor turns public SaaS websites into sales-ready competitor battlecards. It compares your public website against competitor pages and generates positioning notes, pricing signals, differentiation angles, objection handlers, talk tracks, and recommended next actions.

It is designed for founders, product marketers, sales teams, agencies, and consultants who need fast competitive intelligence without logging into private systems or scraping personal data.

For best results, use competitor product pages, pricing pages, feature pages, or comparison pages instead of only a generic homepage.

### Source-Available, Not Free Resale

This repository is public for evaluation, platform review, and portfolio proof. It is not free open-source software and it does not grant a commercial reuse license.

See [`LICENSE.md`](LICENSE.md). You may view the code and samples to evaluate the workflow, but you may not copy, host, resell, monetize, or use it commercially without written permission.

The paid product is the managed result:

- capped public website extraction;
- model-backed competitor battlecards;
- pricing and packaging observations when public;
- Markdown and JSON delivery;
- safe public-page boundaries;
- optional private deployment or commercial license.

### What It Generates

- Competitor positioning summary
- Pricing and packaging signals
- Likely competitor strengths
- Likely competitor weaknesses
- Differentiation angles
- Sales objection handlers
- Buyer-facing talk tracks
- Landing page takeaways
- Recommended next actions
- Source page metadata

### Input

```json
{
  "yourCompanyUrl": "https://example.com",
  "competitorUrls": [{ "url": "https://example.org" }],
  "buyerPersona": "founder, sales leader, or product marketer",
  "marketContext": "B2B SaaS",
  "reportGoal": "Create a sales-ready competitor battlecard from public website evidence.",
  "language": "English",
  "maxPagesPerCompany": 3,
  "maxCharsPerCompany": 14000,
  "includePricingSignals": true
}
````

### Output

Each successfully processed competitor creates one dataset item with:

- `competitorName`
- `competitorPositioning`
- `pricingSignals`
- `likelyStrengths`
- `likelyWeaknesses`
- `differentiationAngles`
- `objectionHandlers`
- `salesTalkTracks`
- `landingPageTakeaways`
- `recommendedNextActions`
- `confidence`
- `sourcePages`

The Actor also writes `RUN.json` and `BATTLECARDS.md` to the key-value store.

### Local Demo

```powershell
npm install
npm run local-demo
```

Dry-run mode is enabled by default. It fetches public pages and shows the output shape without calling a model.

See [`examples/model-backed-sample.md`](examples/model-backed-sample.md) for a shortened model-backed sample.

### Model-Backed Run

Set these as Apify secrets or local environment variables. Do not commit them.

```text
DRY_RUN=false
LLM_BASE_URL=https://your-openai-compatible-provider/v1
LLM_API_KEY=your-secret-key
LLM_MODEL=your-model-name
MAX_OUTPUT_TOKENS=1600
```

Compatibility aliases are also supported: `UPSTREAM_BASE_URL`, `UPSTREAM_API_KEY`, and `DEFAULT_MODEL`.

If a provider gives only the root domain, such as `https://xcode.best`, the Actor normalizes it to the standard `/v1` API path.

### Monetization Fit

This Actor is a practical pay-per-result tool:

- one dataset item per successfully generated competitor battlecard;
- simple pay-per-event setup with `competitor-battlecard-generated`;
- capped public text extraction;
- no account login;
- no private pages;
- no personal contact scraping;
- structured output that can feed sales enablement, product marketing, CRM notes, or agency reports.

Suggested starter pricing:

- Apify Store pay-per-event: USD 0.19-0.49 per generated competitor battlecard after testing cost and quality.
- Manual service: USD 19-49 for 5 competitor battlecards, delivered as Markdown/CSV.
- Upsell: USD 99-249 for a full competitor pack with rewritten sales copy and landing page recommendations.

See [`APIFY-STORE-LISTING.md`](APIFY-STORE-LISTING.md) for the Store listing package, event pricing notes, private test plan, and approval gates.

### Safety Boundaries

- Public websites only.
- No logins, private pages, credentials, customer data, regulated data, or wallet/payment actions.
- Emails and phone-like contact details are redacted from extracted text.
- The model is instructed not to output scraped contact details or invented claims.
- This is not legal, financial, medical, compliance, or security advice.

# Actor input Schema

## `yourCompanyUrl` (type: `string`):

Public homepage, product page, or pricing page for your SaaS company. Do not use private pages or customer data.

## `competitorUrls` (type: `array`):

Public competitor homepages, product pages, pricing pages, or feature pages.

## `buyerPersona` (type: `string`):

Who the battlecard should help you sell to.

## `marketContext` (type: `string`):

Short context about your category, product, or sales motion.

## `reportGoal` (type: `string`):

What you want the battlecard to optimize for.

## `language` (type: `string`):

Output language.

## `maxPagesPerCompany` (type: `integer`):

Homepage plus prioritized internal pages such as Product, Features, Pricing, Customers, or About.

## `maxCharsPerCompany` (type: `integer`):

Caps public text sent into the model for each company.

## `includePricingSignals` (type: `boolean`):

Include public pricing and packaging observations when available.

## Actor input object example

```json
{
  "yourCompanyUrl": "https://example.com",
  "competitorUrls": [
    {
      "url": "https://example.org"
    }
  ],
  "buyerPersona": "founder, sales leader, or product marketer",
  "marketContext": "B2B SaaS",
  "reportGoal": "Create a sales-ready competitor battlecard from public website evidence.",
  "language": "English",
  "maxPagesPerCompany": 3,
  "maxCharsPerCompany": 14000,
  "includePricingSignals": true
}
```

# 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 = {
    "yourCompanyUrl": "https://example.com",
    "competitorUrls": [
        {
            "url": "https://example.org"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("city-in-the-sky/saas-competitor-battlecard-generator").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 = {
    "yourCompanyUrl": "https://example.com",
    "competitorUrls": [{ "url": "https://example.org" }],
}

# Run the Actor and wait for it to finish
run = client.actor("city-in-the-sky/saas-competitor-battlecard-generator").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 '{
  "yourCompanyUrl": "https://example.com",
  "competitorUrls": [
    {
      "url": "https://example.org"
    }
  ]
}' |
apify call city-in-the-sky/saas-competitor-battlecard-generator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=city-in-the-sky/saas-competitor-battlecard-generator",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "SaaS Competitor Battlecard Generator",
        "description": "Generate AI competitor battlecards, pricing signals, differentiation angles, and sales talk tracks from public SaaS websites.",
        "version": "0.1",
        "x-build-id": "HyoCc0MgjpxbB3Yht"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/city-in-the-sky~saas-competitor-battlecard-generator/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-city-in-the-sky-saas-competitor-battlecard-generator",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/city-in-the-sky~saas-competitor-battlecard-generator/runs": {
            "post": {
                "operationId": "runs-sync-city-in-the-sky-saas-competitor-battlecard-generator",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/city-in-the-sky~saas-competitor-battlecard-generator/run-sync": {
            "post": {
                "operationId": "run-sync-city-in-the-sky-saas-competitor-battlecard-generator",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "yourCompanyUrl",
                    "competitorUrls"
                ],
                "properties": {
                    "yourCompanyUrl": {
                        "title": "Your company URL",
                        "type": "string",
                        "description": "Public homepage, product page, or pricing page for your SaaS company. Do not use private pages or customer data."
                    },
                    "competitorUrls": {
                        "title": "Competitor URLs",
                        "minItems": 1,
                        "maxItems": 10,
                        "type": "array",
                        "description": "Public competitor homepages, product pages, pricing pages, or feature pages.",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "buyerPersona": {
                        "title": "Buyer persona",
                        "maxLength": 250,
                        "type": "string",
                        "description": "Who the battlecard should help you sell to.",
                        "default": "founder, sales leader, or product marketer"
                    },
                    "marketContext": {
                        "title": "Market context",
                        "maxLength": 800,
                        "type": "string",
                        "description": "Short context about your category, product, or sales motion.",
                        "default": "B2B SaaS"
                    },
                    "reportGoal": {
                        "title": "Report goal",
                        "maxLength": 1000,
                        "type": "string",
                        "description": "What you want the battlecard to optimize for.",
                        "default": "Create a sales-ready competitor battlecard from public website evidence."
                    },
                    "language": {
                        "title": "Language",
                        "enum": [
                            "English",
                            "Spanish",
                            "French",
                            "German"
                        ],
                        "type": "string",
                        "description": "Output language.",
                        "default": "English"
                    },
                    "maxPagesPerCompany": {
                        "title": "Max pages per company",
                        "minimum": 1,
                        "maximum": 5,
                        "type": "integer",
                        "description": "Homepage plus prioritized internal pages such as Product, Features, Pricing, Customers, or About.",
                        "default": 3
                    },
                    "maxCharsPerCompany": {
                        "title": "Max extracted characters per company",
                        "minimum": 4000,
                        "maximum": 24000,
                        "type": "integer",
                        "description": "Caps public text sent into the model for each company.",
                        "default": 14000
                    },
                    "includePricingSignals": {
                        "title": "Include pricing signals",
                        "type": "boolean",
                        "description": "Include public pricing and packaging observations when available.",
                        "default": true
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
