# Shoplazza Theme Detector - Bulk Store Analysis (`clintsa/shoplazza-store-theme-detector`) Actor

Identify the themes exposed by public Shoplazza tenant stores. Export JSON or CSV and monitor changes. $1.2 per 1,000 rows plus $0.001 per run.

- **URL**: https://apify.com/clintsa/shoplazza-store-theme-detector.md
- **Developed by:** [Andy Besos](https://apify.com/clintsa) (community)
- **Categories:** E-commerce, Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 store theme observations

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

Shoplazza Theme Detector - Bulk Store Analysis helps you identify the themes exposed by public Shoplazza tenant stores. Export native theme IDs, merchant theme names, published version fields and gallery-name matches for bulk store audits and theme migration research.

Enter tenant slugs or myshoplaza.com URLs. No merchant login or Shoplazza API key is needed. Custom domains are outside the supported input scope. Actor event charges at the default 256 MB memory are **$0.001 per run plus $0.0012 per exported row**: **$1.201 for 1,000 rows**.

Selected fields from a recent successful run; source values can change:

```json
{
  "storeUrl": "https://nova-women.myshoplaza.com/",
  "status": "detected",
  "merchant_theme_name": "Nova 2023",
  "merchant_theme_version": "25.21.0",
  "canonical_theme_name": "Nova",
  "theme_id": "9781ecd4-4f0a-49c1-8242-be3f91492f15"
}
```

### Why use this Shoplazza theme detector?

- **Native identifiers:** keep the exact `theme_id` and `merchant_theme_name` rather than reducing the result to a platform label.
- **Separate versions:** `theme_version_id` is an opaque identifier; `merchant_theme_version` is the exposed release; `merchant_theme_c_version` is a separate C version. Missing values remain `null`.
- **Conservative gallery naming:** known merchant names map to Nova, Hero, Boost, Wind, Apollo, Neptune, Pluto, or Saturn. Each match includes `canonical_match_method` and a link to the [official theme gallery](https://www.shoplazza.com/ecommerce-themes).
- **Bulk observations:** one observation for each selected unique storefront, including explicit diagnostics for invalid URLs, inaccessible pages, and missing settings.
- **Theme changes:** scheduled runs identify new observations and changed native fields, using the storefront URL as a stable identity.

Temporary network and server errors receive bounded retries. Each store is handled separately, so a dead demo does not discard the other results. A run with no detected themes fails visibly after writing diagnostics and its summary.

### Pricing

Pay per event: **$0.001 per start plus $0.0012 per exported observation** at the default 256 MB memory. Platform usage is included; no proxy is used.

| Exported observations in one run | Price at default memory |
| ---: | ---: |
| 1 | $0.0022 |
| 100 | $0.121 |
| 1,000 | $1.201 |
| 10,000 | $12.001 |

The exact formula is `$0.001 × start events + $0.0012 × exported rows`. Apify bills one start event per GB of configured memory, with a minimum of one event. At the default memory this is one event. **Diagnostic/error rows and unchanged observations are billable when exported.** Duplicate inputs and inputs skipped by `maxStores` do not produce rows. Change-only mode omits unchanged detections; the start fee and any exported diagnostic rows still apply. The table describes row counts, not guaranteed throughput within a single run timeout.

### How to use this Actor

Enter tenant slugs, bare tenant hostnames, or full HTTP/HTTPS storefront URLs:

- `nova-women`
- `nova-women.myshoplaza.com`
- `https://nova-women.myshoplaza.com/`
- `https://nova-women.myshoplaza.com/products/example?ref=campaign`

All four normalize to the HTTPS homepage. Paths, preview parameters, fragments, and tracking queries are discarded. Repeated spellings of the same store are checked once; `inputUrl` retains the first spelling. Custom domains are outside the supported input scope.

For one store, use:

```json
{
  "storeUrls": [
    "nova-women.myshoplaza.com"
  ],
  "maxStores": 1
}
```

Click **Start**, inspect the Dataset, then export JSON or CSV. Check status before using a detected theme. Names and versions come from public settings; diagnostic/error rows are also billable, and theme identity can be unavailable.

For a bulk theme table:

```json
{
  "storeUrls": [
    "nova-women.myshoplaza.com",
    "hero-theme-fashion.myshoplaza.com",
    "wind-dp.myshoplaza.com",
    "hifurnishing.myshoplaza.com"
  ],
  "maxStores": 100,
  "maxConcurrency": 5
}
```

Start with the one-store example to inspect the output before supplying a larger list. The default timeout is five minutes. Split large lists into smaller batches or adjust the run timeout to fit your workload. Results are available through Apify's dataset exports, including JSON, CSV, and Excel.

### Monitor new and updated themes

Keep the same `monitorId` across scheduled runs. The first successful observation is `new`; later observations are `unchanged` or `updated`. Native field changes appear in `changedFields`, including theme replacement or release upgrades.

| changeType | Meaning |
| --- | --- |
| `new` | First successfully detected theme for this store in this monitor. |
| `updated` | One or more native theme fields changed since the previous successful observation. |
| `unchanged` | Native theme fields match the last successful observation. |
| `null` | Diagnostic observation; no snapshot is overwritten. |

A theme replacement is an update to the store, not a separate merchant. The Actor does not infer removal from a failed request or from a URL omitted in a later run. A timeout, closed store, password page, or redirect does not prove that a theme was removed.

```json
{
  "storeUrls": ["nova-women.myshoplaza.com"],
  "maxStores": 1,
  "monitorId": "agency-store-audit",
  "onlyChangesSince": "2026-10-01T00:00:00.000Z"
}
```

With `onlyChangesSince`, only new or updated detections observed on or after that time are exported. Unchanged detections are omitted, even if they changed during an earlier run. Diagnostics remain visible. Change timestamps describe when the Actor observed a change, not necessarily when the merchant published it. Avoid overlapping runs that share the same monitor ID.

### API example

Use your Apify token to run the Actor and retrieve its dataset:

```bash
curl --request POST \
  --header "Authorization: Bearer YOUR_APIFY_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{"storeUrls":["nova-women.myshoplaza.com"],"maxStores":1}' \
  'https://api.apify.com/v2/acts/Clintsa~shoplazza-store-theme-detector/run-sync-get-dataset-items'
```

### Input options

| Field | Default | Purpose |
| --- | --- | --- |
| `storeUrls` | Required | String list of tenant slugs, hostnames, or storefront URLs. |
| `maxStores` | `100` | Maximum unique inputs processed, from 1 to 10,000. The prefilled example uses 1. |
| `maxConcurrency` | `5` | Concurrent stores, from 1 to 10. Output order may differ from input order. |
| `monitorId` | `default` | Persistent namespace for independent schedules or audits. |
| `onlyChangesSince` | Unset | ISO 8601 timestamp for new/updated detections; diagnostic rows remain visible. |
| `requestDelayMillis` | `0` | Delay between successive stores per worker, from 0 to 60,000 ms. This is not a global throttle. |

### Output

A representative observation from the public Nova demo has the following shape. Live values can change:

```json
{
  "inputUrl": "nova-women.myshoplaza.com",
  "storeUrl": "https://nova-women.myshoplaza.com/",
  "itemId": "https://nova-women.myshoplaza.com/",
  "finalUrl": "https://nova-women.myshoplaza.com/",
  "sourceUrl": "https://nova-women.myshoplaza.com/",
  "status": "detected",
  "isShoplazza": true,
  "httpStatus": 200,
  "error": null,
  "theme_id": "9781ecd4-4f0a-49c1-8242-be3f91492f15",
  "theme_version_id": "17075",
  "merchant_theme_name": "Nova 2023",
  "merchant_theme_version": "25.21.0",
  "merchant_theme_c_version": "3.6.12",
  "theme_preset": null,
  "theme_type": "standard",
  "updated_at": "2026-04-01 09:02:27",
  "merchant_theme_updated_at": "2025-04-17 10:13:37",
  "canonical_theme_name": "Nova",
  "canonical_match_method": "merchant_theme_name_alias",
  "theme_gallery_url": "https://www.shoplazza.com/ecommerce-themes",
  "scrapedAt": "2026-10-17T12:00:00.000Z",
  "changeType": "new",
  "changedFields": [],
  "changeDetectedAt": "2026-10-17T12:00:00.000Z",
  "firstSeenAt": "2026-10-17T12:00:00.000Z",
  "lastSeenAt": "2026-10-17T12:00:00.000Z"
}
```

The **Store themes** table emphasizes native IDs and versions. The **Theme changes** table emphasizes monitoring. The linked `SUMMARY` record contains requested, unique, selected, successful, failed, and detected store counts; skipped inputs; exported rows; status totals; theme change counts; and the completion time.

Statuses include `detected`, `invalid_url`, `unsupported_redirect`, `http_error`, `network_error`, `invalid_response`, `theme_not_exposed`, `invalid_theme`, and `parse_error`. Missing theme fields do not establish that a store runs another platform. `isShoplazza` stays `null` when the observation is inconclusive.

### Use cases

- Theme developers: find public examples using a known theme family and release.
- Design analysts: compare theme adoption across a supplied merchant sample.
- Agencies: audit supported storefronts before planning a Shoplazza redesign.
- Migration teams: retain native theme identifiers alongside a store inventory.
- B2B research teams: enrich an authorized list with theme and version observations.
- Store operators: schedule checks for unexpected theme switches or upgrades.

For product inventory extraction on another platform, see our [Ecwid Product Catalog Extractor](https://apify.com/Clintsa/ecwid-product-catalog-extractor).

### FAQ

**Can this detect every Shoplazza theme?**
It returns the native fields for any supported storefront exposing the expected theme object. Gallery naming is limited to the eight listed families and explicit Nova aliases. Custom or unfamiliar names remain intact, with a null canonical name.

**Does theme_id identify the gallery theme globally?**
No. It is the native theme installation ID exposed by that store. The public gallery does not provide a verified universal ID mapping. Canonical naming uses an exact merchant-name alias and labels that method; it does not pretend to perform a global ID join.

**Which field is the theme version?**
Use `merchant_theme_version` for the exposed release string. Keep `theme_version_id` and `merchant_theme_c_version` separate. None proves that a store is on the newest available release.

**Do I need a Shoplazza API key or proxy?**
No. The Actor uses public homepage HTML. Private admin APIs are not queried, and proxies are not configured.

**Can I submit custom merchant domains?**
This version accepts only tenant storefronts under `myshoplaza.com`. Redirects to custom domains, login screens, preview pages, or unsupported routes produce diagnostics and are not followed.

**Are failed stores charged?**
Every exported row is charged, including diagnostics. This preserves a complete observation table for the selected input list. If every store fails detection, the run fails after writing its diagnostics and summary; exported rows and the start fee still apply.

### Limitations and responsible use

Only public homepage theme settings are inspected. Hidden, password-protected, blocked, deleted, or heavily customized stores may not expose the expected object. The Actor does not execute storefront JavaScript, bypass access controls, infer a theme from visual appearance, discover merchants, or determine license ownership. Upstream timestamps are preserved without inventing a timezone.

Shoplazza's [Terms of Service](https://www.shoplazza.com/terms) prohibit automated access or monitoring of the Services. Public availability alone is not permission. Obtain appropriate authorization, check the applicable storefront terms and robots directives, and use the Actor lawfully. This tool is independent of Shoplazza and provides no legal assurance about a particular use.

### Support

Open the Actor's Issues tab with your run ID, the affected storefront input, and the observed status. Include the expected public theme field when reporting a detection mismatch. Do not share passwords or private access tokens.

# Actor input Schema

## `storeUrls` (type: `array`):

Required. A list of myshoplaza.com storefront URLs, bare hostnames, or tenant slugs such as nova-women. Uses each HTTPS homepage; paths and query parameters are removed. Duplicate stores are checked once. Custom domains are not supported.

## `maxStores` (type: `integer`):

Maximum distinct inputs to process, including invalid inputs. Defaults to 100. The daily health test checks one official demo. Split large lists into batches that fit the run timeout.

## `maxConcurrency` (type: `integer`):

Number of stores checked at once. Default 5; reduce for slower workloads or gentler request rates.

## `monitorId` (type: `string`):

Persistent namespace for theme comparisons. Reuse the same ID across scheduled runs; use another ID for independent monitoring. Avoid simultaneous runs sharing an ID.

## `onlyChangesSince` (type: `string`):

Optional ISO 8601 timestamp. Exports newly observed or updated theme detections since this timestamp. The first successful observation creates a baseline. Diagnostic rows remain visible.

## `requestDelayMillis` (type: `integer`):

Pause each worker between successive stores. Default 0. Concurrency workers can still run together; this is not a global request throttle.

## Actor input object example

```json
{
  "storeUrls": [
    "nova-women.myshoplaza.com",
    "https://hero-theme-fashion.myshoplaza.com/"
  ],
  "maxStores": 1,
  "maxConcurrency": 5,
  "monitorId": "default",
  "requestDelayMillis": 0
}
```

# Actor output Schema

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

No description

## `summary` (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 = {
    "storeUrls": [
        "nova-women.myshoplaza.com"
    ],
    "maxStores": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("clintsa/shoplazza-store-theme-detector").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 = {
    "storeUrls": ["nova-women.myshoplaza.com"],
    "maxStores": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("clintsa/shoplazza-store-theme-detector").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 '{
  "storeUrls": [
    "nova-women.myshoplaza.com"
  ],
  "maxStores": 1
}' |
apify call clintsa/shoplazza-store-theme-detector --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,clintsa/shoplazza-store-theme-detector"
        }
    }
}
```

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/azDHc1xxQSbqg1nxx/builds/kt2TncbpM82tmg5ng/openapi.json
