# Retail Merchandising Opportunity Agent (`k0nkupa/retail-merchandising-opportunity-agent`) Actor

Finds catalog gaps, pricing checks, markdowns, content fixes, and stock opportunities from public retail catalog data.

- **URL**: https://apify.com/k0nkupa/retail-merchandising-opportunity-agent.md
- **Developed by:** [Tony Le](https://apify.com/k0nkupa) (community)
- **Categories:** AI, Automation, E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

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.

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

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

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.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/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

### What does Retail Merchandising Opportunity Agent do?

Retail Merchandising Opportunity Agent turns public Shopify catalog and competitor data into workflow-ready merchandising actions. Instead of only exporting products, it reports catalog gaps, pricing checks, markdowns, stock risks, content fixes, blocked sources, and summary rows.

The Actor reads public Shopify `products.json` endpoints and public catalog fields. It does not use Shopify Admin APIs, private customer data, checkout data, or internal credentials.

### Why use Retail Merchandising Opportunity Agent?

Generic Shopify scrapers can tell you what products exist. This Actor turns public catalog data into a prioritized task list for ecommerce operators, merchandisers, founders, and agencies.

Common use cases:

- Find competitor products or categories your store may not cover
- Check materially high or low prices against matched competitor products
- Review public markdown and compare-at signals
- Flag own-store products missing images or useful descriptions
- Spot stock risk where a competitor has availability and your matched product appears unavailable
- Schedule repeat runs in Apify and export actions as JSON, CSV, Excel, or through the API

### What data can Retail Merchandising Opportunity Agent extract?

| Field | Type | Description |
| --- | --- | --- |
| `recordType` | string | `catalog_gap`, `pricing_action`, `markdown_action`, `content_fix`, `stock_action`, `matched`, `blocked_or_unavailable`, or `summary` |
| `priority` | string | Action priority: `high`, `medium`, or `low` |
| `confidence` | string | Deterministic confidence: `high`, `medium`, or `low` |
| `actionTitle` | string | Short title suitable for a task list or spreadsheet |
| `actionSummary` | string | Short explanation of the action |
| `recommendedNextStep` | string | Manual next step for a merchandiser |
| `evidence` | array | Structured evidence used to justify the row |
| `deterministicScore` | number | Score from 0 to 100 |
| `aiSummary` / `aiDraft` | string | Optional AI enrichment when `runMode` is `ai` |
| `sourceUrl` | string | Primary product or source URL |

### How to use it

1. Enter your own Shopify storefront URL.
2. Add one or more competitor Shopify storefront URLs.
3. Add optional keywords and focus categories.
4. Set a maximum number of products per store.
5. Choose standard mode or AI-enriched mode.
6. Run the Actor and review the default dataset.

For the default NZ outdoor retail MVP, the reference store is `https://www.bivouac.co.nz` and competitors are `https://dwights.co.nz` and `https://www.gearshop.co.nz`.

### Input

Important fields:

- `ownStoreUrl`: your reference Shopify storefront
- `competitorStoreUrls`: competitor Shopify storefronts
- `keywords`: optional product/category terms to highlight
- `focusCategories`: optional category terms for future focusing and reporting
- `matchThreshold`: score from `0` to `1`; lower values mark more products as matched
- `priceDeltaThresholdPct`: minimum percent difference before matched products become pricing actions
- `includeMatchedProducts`: include non-action matched rows for auditing
- `runMode`: `standard` or `ai`
- `aiApiKey`, `aiBaseUrl`, `aiModel`, `aiMaxRows`: optional AI settings

### Output

You can download the dataset in formats such as JSON, HTML, CSV, or Excel.

Example output:

```json
[
  {
    "recordType": "catalog_gap",
    "priority": "high",
    "confidence": "medium",
    "actionTitle": "Review missing packs product: Example Hiking Pack",
    "recommendedNextStep": "Review the competitor product and decide whether to range, substitute, or ignore it.",
    "sourceUrl": "https://example-competitor.com/products/example-hiking-pack",
    "deterministicScore": 80,
    "evidence": [
      { "label": "Gap reason", "value": "missing_category" }
    ]
  },
  {
    "recordType": "summary",
    "productCount": 250,
    "actionCounts": {
      "catalog_gap": 42,
      "pricing_action": 5
    }
  }
]
````

### AI mode

Standard mode is deterministic and does not require an AI key. AI mode is optional. When enabled, it enriches ready action rows with summaries and drafts using only the structured evidence already generated by the Actor.

AI output is nullable. If you do not provide AI settings, the Actor still produces the deterministic action rows.

### Cost notes

Costs depend mainly on the number of stores and products scanned. The Actor uses simple HTTP requests against public Shopify JSON endpoints and does not launch a browser by default, so it should be cheaper than browser-based scraping for stores that expose `products.json`.

Start with a low `maxProductsPerStore` value such as `50` to inspect output quality, then increase it for fuller catalog comparisons.

### FAQ, disclaimers, and support

This Actor only reads public Shopify catalog data. It does not extract private customer data, checkout data, or account data.

Use the results for legitimate competitive research, merchandising review, and catalog operations. Check source website terms and applicable laws before scraping at scale or using the output in commercial workflows.

For programmatic usage, use the Apify API tab after deployment. For feedback, open an issue on the Actor page.

# Actor input Schema

## `ownStoreUrl` (type: `string`):

Reference Shopify storefront URL. The Actor compares competitors against this catalog.

## `competitorStoreUrls` (type: `array`):

Competitor Shopify storefront URLs to compare against the own store.

## `keywords` (type: `array`):

Optional keywords used to flag important product or category gaps.

## `focusCategories` (type: `array`):

Optional categories or category-like terms used to focus merchandising actions.

## `maxProductsPerStore` (type: `integer`):

Maximum number of products to fetch from each Shopify catalog.

## `matchThreshold` (type: `number`):

Score from 0 to 1. Competitor products below this score are reported as gaps.

## `priceDeltaThresholdPct` (type: `integer`):

Minimum percent difference before a matched product becomes a pricing action.

## `includeMatchedProducts` (type: `boolean`):

When enabled, include competitor products that appear covered by the own catalog.

## `includeSummary` (type: `boolean`):

Emit one summary row per competitor store.

## `currency` (type: `string`):

Currency code used to label prices. Shopify products.json prices do not include currency.

## `runMode` (type: `string`):

Use standard for deterministic rows only, or ai for optional AI summaries and drafts.

## `aiApiKey` (type: `string`):

Optional OpenAI-compatible API key. Required only when run mode is ai.

## `aiBaseUrl` (type: `string`):

OpenAI-compatible base URL.

## `aiModel` (type: `string`):

OpenAI-compatible chat model name.

## `aiMaxRows` (type: `integer`):

Maximum number of ready action rows to enrich with AI in one run.

## Actor input object example

```json
{
  "ownStoreUrl": "https://www.bivouac.co.nz",
  "competitorStoreUrls": [
    "https://dwights.co.nz",
    "https://www.gearshop.co.nz"
  ],
  "keywords": [
    "hiking",
    "boots",
    "tent",
    "pack",
    "sleeping bag"
  ],
  "focusCategories": [
    "footwear",
    "packs",
    "camping"
  ],
  "maxProductsPerStore": 250,
  "matchThreshold": 0.45,
  "priceDeltaThresholdPct": 15,
  "includeMatchedProducts": false,
  "includeSummary": true,
  "currency": "NZD",
  "runMode": "standard",
  "aiBaseUrl": "https://api.openai.com/v1",
  "aiModel": "gpt-4.1-mini",
  "aiMaxRows": 25
}
```

# Actor output Schema

## `merchandisingActions` (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 = {
    "ownStoreUrl": "https://www.bivouac.co.nz",
    "competitorStoreUrls": [
        "https://dwights.co.nz",
        "https://www.gearshop.co.nz"
    ],
    "keywords": [
        "hiking",
        "boots",
        "tent",
        "pack",
        "sleeping bag"
    ],
    "focusCategories": [
        "footwear",
        "packs",
        "camping"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("k0nkupa/retail-merchandising-opportunity-agent").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 = {
    "ownStoreUrl": "https://www.bivouac.co.nz",
    "competitorStoreUrls": [
        "https://dwights.co.nz",
        "https://www.gearshop.co.nz",
    ],
    "keywords": [
        "hiking",
        "boots",
        "tent",
        "pack",
        "sleeping bag",
    ],
    "focusCategories": [
        "footwear",
        "packs",
        "camping",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("k0nkupa/retail-merchandising-opportunity-agent").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 '{
  "ownStoreUrl": "https://www.bivouac.co.nz",
  "competitorStoreUrls": [
    "https://dwights.co.nz",
    "https://www.gearshop.co.nz"
  ],
  "keywords": [
    "hiking",
    "boots",
    "tent",
    "pack",
    "sleeping bag"
  ],
  "focusCategories": [
    "footwear",
    "packs",
    "camping"
  ]
}' |
apify call k0nkupa/retail-merchandising-opportunity-agent --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=k0nkupa/retail-merchandising-opportunity-agent",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Retail Merchandising Opportunity Agent",
        "description": "Finds catalog gaps, pricing checks, markdowns, content fixes, and stock opportunities from public retail catalog data.",
        "version": "0.1",
        "x-build-id": "shmaC1cjHx6GfZGdN"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/k0nkupa~retail-merchandising-opportunity-agent/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-k0nkupa-retail-merchandising-opportunity-agent",
                "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/k0nkupa~retail-merchandising-opportunity-agent/runs": {
            "post": {
                "operationId": "runs-sync-k0nkupa-retail-merchandising-opportunity-agent",
                "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/k0nkupa~retail-merchandising-opportunity-agent/run-sync": {
            "post": {
                "operationId": "run-sync-k0nkupa-retail-merchandising-opportunity-agent",
                "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": [
                    "ownStoreUrl",
                    "competitorStoreUrls"
                ],
                "properties": {
                    "ownStoreUrl": {
                        "title": "Own store URL",
                        "type": "string",
                        "description": "Reference Shopify storefront URL. The Actor compares competitors against this catalog."
                    },
                    "competitorStoreUrls": {
                        "title": "Competitor store URLs",
                        "type": "array",
                        "description": "Competitor Shopify storefront URLs to compare against the own store.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "keywords": {
                        "title": "Keywords",
                        "type": "array",
                        "description": "Optional keywords used to flag important product or category gaps.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "focusCategories": {
                        "title": "Focus categories",
                        "type": "array",
                        "description": "Optional categories or category-like terms used to focus merchandising actions.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxProductsPerStore": {
                        "title": "Max products per store",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Maximum number of products to fetch from each Shopify catalog.",
                        "default": 250
                    },
                    "matchThreshold": {
                        "title": "Match threshold",
                        "minimum": 0,
                        "maximum": 1,
                        "type": "number",
                        "description": "Score from 0 to 1. Competitor products below this score are reported as gaps.",
                        "default": 0.45
                    },
                    "priceDeltaThresholdPct": {
                        "title": "Price delta threshold percent",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Minimum percent difference before a matched product becomes a pricing action.",
                        "default": 15
                    },
                    "includeMatchedProducts": {
                        "title": "Include matched products",
                        "type": "boolean",
                        "description": "When enabled, include competitor products that appear covered by the own catalog.",
                        "default": false
                    },
                    "includeSummary": {
                        "title": "Include summary rows",
                        "type": "boolean",
                        "description": "Emit one summary row per competitor store.",
                        "default": true
                    },
                    "currency": {
                        "title": "Currency",
                        "type": "string",
                        "description": "Currency code used to label prices. Shopify products.json prices do not include currency.",
                        "default": "NZD"
                    },
                    "runMode": {
                        "title": "Run mode",
                        "enum": [
                            "standard",
                            "ai"
                        ],
                        "type": "string",
                        "description": "Use standard for deterministic rows only, or ai for optional AI summaries and drafts.",
                        "default": "standard"
                    },
                    "aiApiKey": {
                        "title": "AI API key",
                        "type": "string",
                        "description": "Optional OpenAI-compatible API key. Required only when run mode is ai."
                    },
                    "aiBaseUrl": {
                        "title": "AI base URL",
                        "type": "string",
                        "description": "OpenAI-compatible base URL.",
                        "default": "https://api.openai.com/v1"
                    },
                    "aiModel": {
                        "title": "AI model",
                        "type": "string",
                        "description": "OpenAI-compatible chat model name.",
                        "default": "gpt-4.1-mini"
                    },
                    "aiMaxRows": {
                        "title": "AI max rows",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Maximum number of ready action rows to enrich with AI in one run.",
                        "default": 25
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
