# Landing Page Experiment Planner (`danielmichalek/landing-page-ab-hypothesis-generator`) Actor

Turn up to 50 supplied landing page audits into experiment cards. Each card includes source evidence, a proposed change, a conversion metric and guardrails. Send your audit JSON to prepare a plan for review.

- **URL**: https://apify.com/danielmichalek/landing-page-ab-hypothesis-generator.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

$30.00 / 1,000 landing page experiment plans

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

## Landing Page Experiment Planner

Turn supplied landing page audit findings into a reviewable experiment backlog. The Actor connects a source observation to one proposed change, a primary conversion metric, a guardrail and explicit prerequisites. Agencies can use the output after an audit to prepare a client experiment brief.

### What it does

The planner accepts up to 50 page audits and supports four finding IDs from the factory's landing page auditor. `message_match` produces a hero headline proposal tied to the supplied approved promise. `cta` produces a primary action proposal. `form_length` produces a conversion form proposal whose relevance the owner must review. `trust_signals` proposes placement of authentic evidence supplied and cleared by the customer.

Each experiment retains the original finding ID, status and message. Priority reflects source severity. Access, HTTPS, privacy, consent and analytics findings produce prerequisite fixes. PASS and INFO findings produce skipped records. Unknown IDs are preserved in the skipped summary.

### Input

Provide `conversionGoal` as `lead_submission`, `purchase` or `signup`. Set `measurementReady` only after confirming the actual conversion event, eligible visitor denominator, assignment and guardrail measurement. This declaration remains customer supplied evidence.

Each page needs a unique `pageId` and a `findings` array. Findings use `id`, `status` and `message`. Status is exactly PASS, WARN, FAIL or INFO. Supply `adPromise` to prepare a hero headline variant. Set `verifiedTrustEvidence` only after authentic evidence and permissions have been reviewed.

The limits are 50 pages, 40 findings per page, 2000 Unicode code points per message and 1,500,000 UTF-8 bytes for the complete input. The Actor validates nested objects and duplicate IDs. URL identifiers are retained with query strings and fragments removed. Embedded URL credentials are rejected.

### Output

One dataset row contains the complete JSON report, including `pages`, `experiments`, `prerequisites` and `skipped`. EXPERIMENT_PLAN stores the same report. EXPERIMENT_CSV contains one row per proposed experiment. REPORT provides a readable summary.

A card includes the source finding, control, proposed change, hypothesis mechanism, primary metric, guardrail, prerequisite IDs and an applicability review. `readyForReview` describes supplied prerequisites. Every card still requires review, and `effectExecuted` remains false.

CSV cells that resemble formulas and numeric page IDs receive a leading apostrophe for spreadsheet import. The JSON report retains original page IDs. Import the ID column as text when IDs resemble dates or scientific notation.

### Pricing and cost control

One experiment-plan-report covers up to 50 supplied landing page audits. The Store displays the current price for the complete report before a run. Send your audit JSON to prepare cards with source evidence, metrics and prerequisites.

PRICING.json preserves the original USD 0.03 report proposal and USD 0.002 engineering planning allowance. Release receipts record price activation, cloud observations and public readback. The adjacent historical benchmark uses a different unit. Operating cost and margin require measurements for the intended workload and storage retention.

The runtime caps delivery at one dataset row, zero HTTP requests and 45 seconds of processing. The proposed cloud configuration is 256 MB and 60 seconds. Dependency versions are locked. Local acceptance uses the installed Apify SDK.

### Limitations and fair use

Results are deterministic rules over customer supplied findings. Source observations and readiness declarations require validation by the owner. The planner produces draft experiment cards. Sample size, experiment duration, stopping rules and causal conclusions require an appropriate experiment design.

The audit's detected form may differ from the conversion form. Confirm applicability before approving a field change. Claims, testimonials and guarantees need authentic evidence and permission. Data should be limited to authorized page observations.

### Resume and error handling

PLAN_DELIVERY records PREPARED before delivery and COMPLETE after one confirmed dataset write and the expected named event. A completed repeat validates JSON, CSV, the readable report, runtime, pricing and the physical dataset. It returns a reused result with zero additional emission.

RECONCILIATION_REQUIRED preserves the existing storage after uncertain delivery or changed input. Review the prior run and its artifacts before another operation. PRICING_UNVERIFIED stops before delivery when the charging model is unavailable. INVALID_INPUT identifies a bounded input contract violation without echoing supplied content.

### Example

Use the exact input in `examples/input.json`, also provided as the input form prefill. It includes a lead page with four supported findings and a second page whose access failure requires repair. The resulting report contains four experiment cards and four prerequisites.

For a fresh checkout, run `npm ci --ignore-scripts --no-audit --no-fund`, then `npm test`. Start with `npm start` and a new local storage directory containing INPUT.json. Factory acceptance used the reviewed offline dependency cache. The SDK entry point retains storage so that a verified completed replay can be inspected.

# Actor input Schema

## `conversionGoal` (type: `string`):

Choose the customer action measured by the proposed experiment.

## `measurementReady` (type: `boolean`):

Set true only after confirming the conversion event, eligible visitor denominator, assignment and guardrail measurements. Detection of analytics in HTML alone does not establish readiness.

## `pages` (type: `array`):

Supply 1 to 50 page objects with unique pageId and at most 40 findings each. Use the landing-page-ad-audit finding IDs and exact PASS, WARN, FAIL or INFO statuses. The complete input is limited to 1.5 MB.

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

One complete report contains all supplied pages, experiment cards and prerequisites.

## Actor input object example

```json
{
  "conversionGoal": "lead_submission",
  "measurementReady": false,
  "pages": [
    {
      "pageId": "lead-home",
      "url": "https://example.com/offer",
      "ok": true,
      "adPromise": "Book a 15 minute product walkthrough",
      "verifiedTrustEvidence": false,
      "findings": [
        {
          "id": "fetch",
          "status": "PASS",
          "message": "The page returned HTTP 200."
        },
        {
          "id": "message_match",
          "status": "WARN",
          "message": "Ad copy token overlap was 40 percent."
        },
        {
          "id": "cta",
          "status": "WARN",
          "message": "Seven possible calls to action were detected."
        },
        {
          "id": "form_length",
          "status": "WARN",
          "message": "The selected form contains ten required fields."
        },
        {
          "id": "trust_signals",
          "status": "FAIL",
          "message": "No supported trust signal type was detected."
        },
        {
          "id": "analytics",
          "status": "PASS",
          "message": "An analytics script was detected in HTML."
        }
      ]
    },
    {
      "pageId": "contact",
      "url": "https://example.com/contact",
      "ok": false,
      "findings": [
        {
          "id": "fetch",
          "status": "FAIL",
          "message": "The page could not be fetched."
        },
        {
          "id": "cta",
          "status": "FAIL",
          "message": "The supplied audit has no recognized CTA."
        }
      ]
    }
  ],
  "maxItems": 1
}
```

# Actor output Schema

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

No description

## `plan` (type: `string`):

No description

## `csv` (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 = {
    "conversionGoal": "lead_submission",
    "pages": [
        {
            "pageId": "lead-home",
            "url": "https://example.com/offer",
            "ok": true,
            "adPromise": "Book a 15 minute product walkthrough",
            "verifiedTrustEvidence": false,
            "findings": [
                {
                    "id": "fetch",
                    "status": "PASS",
                    "message": "The page returned HTTP 200."
                },
                {
                    "id": "message_match",
                    "status": "WARN",
                    "message": "Ad copy token overlap was 40 percent."
                },
                {
                    "id": "cta",
                    "status": "WARN",
                    "message": "Seven possible calls to action were detected."
                },
                {
                    "id": "form_length",
                    "status": "WARN",
                    "message": "The selected form contains ten required fields."
                },
                {
                    "id": "trust_signals",
                    "status": "FAIL",
                    "message": "No supported trust signal type was detected."
                },
                {
                    "id": "analytics",
                    "status": "PASS",
                    "message": "An analytics script was detected in HTML."
                }
            ]
        },
        {
            "pageId": "contact",
            "url": "https://example.com/contact",
            "ok": false,
            "findings": [
                {
                    "id": "fetch",
                    "status": "FAIL",
                    "message": "The page could not be fetched."
                },
                {
                    "id": "cta",
                    "status": "FAIL",
                    "message": "The supplied audit has no recognized CTA."
                }
            ]
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("danielmichalek/landing-page-ab-hypothesis-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 = {
    "conversionGoal": "lead_submission",
    "pages": [
        {
            "pageId": "lead-home",
            "url": "https://example.com/offer",
            "ok": True,
            "adPromise": "Book a 15 minute product walkthrough",
            "verifiedTrustEvidence": False,
            "findings": [
                {
                    "id": "fetch",
                    "status": "PASS",
                    "message": "The page returned HTTP 200.",
                },
                {
                    "id": "message_match",
                    "status": "WARN",
                    "message": "Ad copy token overlap was 40 percent.",
                },
                {
                    "id": "cta",
                    "status": "WARN",
                    "message": "Seven possible calls to action were detected.",
                },
                {
                    "id": "form_length",
                    "status": "WARN",
                    "message": "The selected form contains ten required fields.",
                },
                {
                    "id": "trust_signals",
                    "status": "FAIL",
                    "message": "No supported trust signal type was detected.",
                },
                {
                    "id": "analytics",
                    "status": "PASS",
                    "message": "An analytics script was detected in HTML.",
                },
            ],
        },
        {
            "pageId": "contact",
            "url": "https://example.com/contact",
            "ok": False,
            "findings": [
                {
                    "id": "fetch",
                    "status": "FAIL",
                    "message": "The page could not be fetched.",
                },
                {
                    "id": "cta",
                    "status": "FAIL",
                    "message": "The supplied audit has no recognized CTA.",
                },
            ],
        },
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("danielmichalek/landing-page-ab-hypothesis-generator").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 '{
  "conversionGoal": "lead_submission",
  "pages": [
    {
      "pageId": "lead-home",
      "url": "https://example.com/offer",
      "ok": true,
      "adPromise": "Book a 15 minute product walkthrough",
      "verifiedTrustEvidence": false,
      "findings": [
        {
          "id": "fetch",
          "status": "PASS",
          "message": "The page returned HTTP 200."
        },
        {
          "id": "message_match",
          "status": "WARN",
          "message": "Ad copy token overlap was 40 percent."
        },
        {
          "id": "cta",
          "status": "WARN",
          "message": "Seven possible calls to action were detected."
        },
        {
          "id": "form_length",
          "status": "WARN",
          "message": "The selected form contains ten required fields."
        },
        {
          "id": "trust_signals",
          "status": "FAIL",
          "message": "No supported trust signal type was detected."
        },
        {
          "id": "analytics",
          "status": "PASS",
          "message": "An analytics script was detected in HTML."
        }
      ]
    },
    {
      "pageId": "contact",
      "url": "https://example.com/contact",
      "ok": false,
      "findings": [
        {
          "id": "fetch",
          "status": "FAIL",
          "message": "The page could not be fetched."
        },
        {
          "id": "cta",
          "status": "FAIL",
          "message": "The supplied audit has no recognized CTA."
        }
      ]
    }
  ]
}' |
apify call danielmichalek/landing-page-ab-hypothesis-generator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,danielmichalek/landing-page-ab-hypothesis-generator"
        }
    }
}
```

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/MP5Uo4cttfeVSkib1/builds/AQbqE1qDVzrmmQ8ST/openapi.json
