# Shopify CSV ChangeGuard — Price & Overwrite Risks (`analytical_gratefulness/shopify-catalog-changeguard`) Actor

Compare AI-edited Shopify product CSVs before import: price drops, blank overwrites and variant identity risks. Structured BLOCK/REVIEW results. $1.50/report, usage included. No store login.

- **URL**: https://apify.com/analytical\_gratefulness/shopify-catalog-changeguard.md
- **Developed by:** [black cow](https://apify.com/analytical_gratefulness) (community)
- **Categories:** E-commerce, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1,500.00 / 1,000 csv change-risk reports

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Shopify CSV ChangeGuard — Price & Overwrite Risks

Before importing an edited product CSV, compare it with your original export. Find accidental price jumps, blank overwrites, and variant identity changes without connecting your store.

**$1.50 per completed report. Platform usage included. No per-row fee.** The synthetic demo has no report event charge. A completed report with warnings or errors is still a report; malformed or unsupported input is rejected without a custom report charge. Your own build/run/storage use is subject to your Apify plan.

### For AI agents: review CSV edits before a Shopify import

Use this tool after an agent edits a Shopify product CSV and before the operator decides whether to import it. It compares the original export with the proposed file, without changing either file or the store. For a single-file format check, use the separate Preflight product linked below.

Find `Shopify CSV ChangeGuard` through [Apify MCP](https://docs.apify.com/integrations/mcp), or connect the [specific Actor tool](https://mcp.apify.com?tools=analytical_gratefulness/shopify-catalog-changeguard\&telemetry-enabled=false). Search/details can be anonymous; execution needs the customer's authorized Apify authentication or a supported agentic payment flow. Use the customer's budget, never a developer's shared token. Being discoverable does not mean a payment has occurred.

1. Read the input schema and price. Use `{"mode":"demo"}` only to inspect synthetic output; do not attach real CSVs to demo mode.
2. For actual files, explicitly set `mode="compare"` and supply both CSV texts. Confirm `same_currency=true` only when the operator knows the currency matches. Keep `partial_update` for a subset of the catalog.
3. Before running, authorize the $1.50 report price in the customer's workflow. A report with risks is billable. A new run is a new report: do not retry successful runs to retrieve output; read the existing run's result. This product does not deduplicate billing across separate runs.
4. Check `complete`, `report_kind` and `workflow.decision` before reading the findings. A synthetic report is not a validation of customer files. On `REJECTED`, inspect the fixed error message; no custom report event was charged.
5. Use `issue_counts_by_code` for complete counts even if `issues_truncated=true`. Individual findings locate the physical CSV line and known field without echoing raw values. Consult `coverage` for price comparison and unverified areas.

| Decision | Meaning for the calling workflow |
|---|---|
| `BLOCK` | Errors were found. Hold the proposed import and correct the flagged problems. |
| `REVIEW` | Warnings need review, including unconfirmed currency or identity changes. |
| `NO_FLAGGED_RISKS` | Implemented checks found no warning/error. Review unverified scope; this is not permission or a guarantee to import. |
| `REJECTED` | No completed comparison. Correct the input before requesting a new report. |

`workflow.import_authorized` is always `false`. Shopify permissions, live store state and the final import decision remain in the customer's workflow. Existing report fields and `schema_version=1` remain compatible; workflow version 1, coverage and code counts are additive.

#### Synthetic compare request ($1.50 report event)

```json
{
  "mode": "compare",
  "baseline_csv": "Handle,Title,Option1 Name,Option1 Value,Variant Price,Vendor,Variant SKU\nlinen-shirt,Linen shirt,Size,S,30,Studio,SHIRT-S\n",
  "candidate_csv": "Handle,Title,Option1 Name,Option1 Value,Variant Price,Vendor,Variant SKU\nlinen-shirt,Linen shirt,Size,S,3,,SHIRT-S\n",
  "comparison_mode": "partial_update",
  "same_currency": true,
  "price_change_percent": 20,
  "delete_input_after_read": true
}
```

Expected summary: `report_kind="customer_comparison"`, `complete=true`, `status="FAIL"`, `workflow.decision="BLOCK"`, and counts `BLANK_OVERWRITE: 1`, `PRICE_JUMP: 1`. Here “customer\_comparison” identifies compare mode, not proof of an external customer or revenue. The files above are synthetic. Try the [saved CSV price-drop example](https://apify.com/analytical_gratefulness/shopify-catalog-changeguard/examples/check-shopify-csv-price-drops-before-import) or use the free synthetic demo first.

### Example: catch a 90% price drop before import

The included demo changes a shirt price from 30 to 3 and clears its vendor. The report flags `PRICE_JUMP` at -90% and `BLANK_OVERWRITE`, with file and row references. It does not return the original cell values.

### Run it

1. Choose **Try synthetic example** to see the output first.
2. Choose **Compare my two CSV files**, and paste the original and proposed product CSV texts.
3. Keep **Partial update** when the proposed CSV intentionally includes only some products. Use **Full snapshot** to report unmatched baseline rows.
4. Confirm **Both files use the same store currency** to enable price percentage comparisons. The default warning threshold is 20% in either direction; adjust it to your workflow.
5. Open **Risks by row** in the output dataset. Use file/row/field references to inspect your original files. Download the full report from the run output.

**Import assumption:** You intend to select Shopify's overwrite-matching-handles option. If that option is off, matching existing products are ignored by Shopify. An omitted column differs from a blank cell. Missing CSV rows are never labeled as product deletions.

### What it checks

- Price increases/decreases at or above your threshold, prices changed to zero, and undefined changes from zero.
- Previously populated known fields changed to blank, with separate product-level and variant-level handling.
- Option/handle changes suggested by a unique SKU; SKU is supporting evidence, not Shopify's update key.
- Duplicate variant keys and duplicate SKUs; ambiguous matches are not guessed.
- Missing variant dependencies, malformed monetary values, formula-like cells, and omitted columns.
- Full-snapshot rows that are unmatched, with a warning that CSV omission does not delete products.

Continuation rows and image-only rows are handled separately. Reordered variants do not turn structural blank product cells into overwrite warnings.

### Limits and privacy

- UTF-8 CSV, at most 8 MiB per file, 12 MiB combined, 50,000 rows per file, 128 columns, and 128 KiB characters per field.
- Reports contain at most 500 findings; counts still include additional findings. Decimal price comparisons accept up to 18 integer and 8 fractional digits.
- No Shopify login, API key, external AI, URL fetching, or automatic modification of products/files.
- Apify receives the supplied input. **Remove this run’s input record after reading** defaults to enabled. Disable it only if you need the original input retained for reruns. Removal covers this run's INPUT record, not backups or other copies.
- Reports omit raw product names, SKUs, prices, URLs, and unknown column names. Findings can contain percentage changes and row counts. Protect report access links.
- Do not submit customer, payment, credential, or confidential personal data. Recognized private-data columns are rejected, but this is not a universal personal-data detector.
- Unknown/metafield/market-specific columns, remote image availability, live store state, third-party app behavior, and actual Shopify import acceptance are not verified. A PASS means no flagged issue in the implemented checks, not guaranteed import safety.

For checking the format of a single file, use [Shopify Product CSV Preflight](https://apify.com/analytical_gratefulness/shopify-catalog-preflight). ChangeGuard compares the impact of edits between two files.

### Offline use

The source package's local CLI needs Python 3.12 or newer and no third-party packages. It makes no network requests and does not read environment credentials.

```sh
python -m catalog_changeguard examples/baseline.csv examples/candidate.csv --same-currency
python -m catalog_changeguard before.csv after.csv --same-currency --threshold 20 --report report.json
```

The report path must be new; output files are created with user-only permissions. Exit codes: 0 for PASS/WARN, 1 for a completed FAIL report, 2 for rejected input or file errors. No CSV rewrite is produced.

Rules are grounded in [Shopify's product CSV documentation](https://help.shopify.com/en/manual/products/import-export/using-csv). This product is independently developed and is not affiliated with Shopify.

# Actor input Schema

## `mode` (type: `string`):

Demo accepts no supplied CSV texts and never validates your files. Compare produces one $1.50 report, including reports with risks. Always set mode explicitly in API/MCP calls.

## `baseline_csv` (type: `string`):

Paste a product-only UTF-8 CSV export. Both files need Handle. Apify receives this input; do not include customer, payment, or credential data.

## `candidate_csv` (type: `string`):

Paste the proposed CSV. At most 8 MiB per file, 12 MiB combined, and 50,000 rows per file.

## `comparison_mode` (type: `string`):

Neither mode treats a missing CSV row as a Shopify product deletion. Comparison assumes overwrite matching handles is selected during import.

## `same_currency` (type: `boolean`):

Confirm this to enable price percentage comparisons. Without confirmation, price percentages are skipped. Market-specific price columns are not compared.

## `price_change_percent` (type: `number`):

Applies to increases and decreases after same-currency confirmation. 20% is a starting threshold, not a statistically optimized value.

## `delete_input_after_read` (type: `boolean`):

Recommended for privacy. The original CSV texts will no longer be available in this run’s INPUT record for reruns. This does not erase platform backups or other copies. Reports omit raw cell values.

## Actor input object example

```json
{
  "mode": "demo",
  "comparison_mode": "partial_update",
  "same_currency": false,
  "price_change_percent": 20,
  "delete_input_after_read": true
}
```

# Actor output Schema

## `reports` (type: `string`):

No description

## `report_json` (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 = {
    "mode": "demo",
    "comparison_mode": "partial_update",
    "same_currency": false,
    "price_change_percent": 20,
    "delete_input_after_read": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("analytical_gratefulness/shopify-catalog-changeguard").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 = {
    "mode": "demo",
    "comparison_mode": "partial_update",
    "same_currency": False,
    "price_change_percent": 20,
    "delete_input_after_read": True,
}

# Run the Actor and wait for it to finish
run = client.actor("analytical_gratefulness/shopify-catalog-changeguard").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 '{
  "mode": "demo",
  "comparison_mode": "partial_update",
  "same_currency": false,
  "price_change_percent": 20,
  "delete_input_after_read": true
}' |
apify call analytical_gratefulness/shopify-catalog-changeguard --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,analytical_gratefulness/shopify-catalog-changeguard"
        }
    }
}

```

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/NBRU3b15dNv4bww9f/builds/U7nYZyczIOZSxCwtD/openapi.json
