# ShopBack Scraper & Affiliate Network Detector (`automation_craft/affiliate-network-detector`) Actor

Detect a brand's active affiliate network via ShopBack click-out, and/or scrape ShopBack merchant page details (cashback rates, terms, vouchers). Mode-selectable per run.

- **URL**: https://apify.com/automation\_craft/affiliate-network-detector.md
- **Developed by:** [Automation Craft](https://apify.com/automation_craft) (community)
- **Categories:** E-commerce, Marketing
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

Pay per event

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.

- **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

ShopBack Scraper & Affiliate Network Detector pulls two kinds of data from [ShopBack](https://www.shopback.com.au) merchant pages: the **brand's currently-active affiliate network** (Commission Factory, Partnerize, Impact, AWIN, CJ, Rakuten, Amazon Associates…) and the **merchant page details** (cashback rates, upsized boosts, terms, vouchers, categories). Pick what you want per run with a single `mode` setting. Run it on the [Apify platform](https://apify.com) for API access, scheduling, proxy rotation, and integrations with Make, Zapier, Google Sheets, and more.

### What does this Actor do?

Instead of scraping a brand's own website for affiliate tags (brittle, and it surfaces stale/legacy tags the brand no longer uses), this Actor reads the network out of **ShopBack's click-out redirect**. ShopBack is a major cashback publisher that only earns when it tracks through the brand's **live** program — so the network in its click-out is the brand's real, current affiliate provider. It can't be a stale tag, because a stale tag wouldn't pay ShopBack.

It can also extract the structured details ShopBack shows on each merchant page, so the same run can power cashback-rate monitoring and competitive research.

### Why use it?

- **Accurate affiliate attribution** — current, not legacy. No misallocation from old tags.
- **Honest outcomes** — a brand that genuinely isn't on ShopBack returns `not_on_shopback`, not a vague failure.
- **Cost-aware** — a two-axis escalation ladder (HTTP → browser; direct → datacenter → residential proxy) pays for expensive residential proxy only when a site actually blocks cheaper tiers.
- **Two products, one run** — `both` mode reuses a single page load to return affiliate **and** details together.

### How to use it

1. Open the **Input** tab.
2. Choose a **mode**: `affiliate`, `details`, or `both`.
3. Add **targets** — each `input` is either a company domain (`2xu.com`) or a ShopBack URL (`shopback.com.au/2xu`). Add an optional `brand` to improve resolution and a `rowNumber` to map results back to a spreadsheet row.
4. **For `affiliate` / `both` modes, paste a ShopBack session cookie** (`shopbackSessionCookie`) — ShopBack's click-out only exists when you're logged in. See [Session cookie](#session-cookie-affiliate--both-modes) below. `details` mode needs no cookie.
5. Pick your **region** (`au` by default).
6. Click **Start**. Download results from the **Output** tab as JSON, CSV, Excel, or HTML, or read them via the API.

#### Session cookie (affiliate / both modes)

ShopBack shows the "Shop Now" click-out — the redirect that reveals the live affiliate network — **only to logged-in users**. The Actor doesn't automate login (it's protected by Cloudflare Turnstile + OTP). Instead you supply your own session once:

1. Log in to ShopBack in your browser.
2. Export the `shopback.com.au` cookies with a browser extension like **Cookie-Editor** (use "Export → JSON").
3. Paste the JSON into the encrypted **`shopbackSessionCookie`** input. It **must include the `sbrefresh` cookie** — that's the long-lived refresh token that keeps the session alive.

The session is **sliding**: ShopBack issues a fresh short-lived access token from your refresh token, and the Actor writes the freshest cookies back to its key-value store after every run. So as long as you run the Actor on a schedule, you **paste once and basically forget**. If the session ever truly dies, the run returns `auth_expired` and you re-paste.

### Modes

| Mode        | Loads page | Fires click-out | Returns                 | Relative cost  |
| ----------- | ---------- | --------------- | ----------------------- | -------------- |
| `details`   | yes        | no              | `details`               | cheapest       |
| `affiliate` | yes        | yes             | `affiliate`             | tier-dependent |
| `both`      | yes (once) | yes             | `affiliate` + `details` | ≈ `affiliate`  |

### Input

| Field            | Type    | Description                                                                               |
| ---------------- | ------- | ----------------------------------------------------------------------------------------- |
| `mode`                  | string  | `affiliate` (default), `details`, or `both`.                                              |
| `targets`               | array   | Each item: `{ input, brand?, rowNumber? }`. `input` = company domain **or** ShopBack URL. |
| `shopbackSessionCookie` | string  | **Required for `affiliate`/`both`.** Cookie-Editor JSON of your ShopBack session (must include `sbrefresh`). Encrypted; never logged. |
| `region`                | string  | `au` (default), `sg`, `my`, `global`.                                                     |
| `maxConcurrency`        | integer | Parallel targets (default 5).                                                             |
| `forceBrowser`          | boolean | Skip the HTTP fast path (reserved).                                                       |

```json
{
    "mode": "both",
    "region": "au",
    "targets": [
        { "input": "2xu.com", "brand": "2XU", "rowNumber": 137 },
        { "input": "shopback.com.au/nike", "brand": "Nike" }
    ]
}
```

### Output

One dataset item per target:

```json
{
    "input": "2xu.com",
    "brand": "2XU",
    "rowNumber": 137,
    "mode": "both",
    "shopbackUrl": "https://www.shopback.com.au/2xu",
    "cleanDomain": "2xu.com",
    "resolvedVia": "search",
    "outcome": "resolved",
    "affiliate": {
        "network": "Rakuten Advertising",
        "status": "network_identified",
        "matchedHost": "click.linksynergy.com",
        "redirectChain": [
            "https://www.shopback.com.au/2xu",
            "https://www.shopback.com.au/sboc/redirects/01jq8w85tnwyesa2y0tv2ssyvj",
            "https://click.linksynergy.com/deeplink?id=...&mid=44490&murl=https%3a%2f%2f2xu.com%2f",
            "https://2xu.com/?utm_source=Rakuten&ranMID=44490..."
        ]
    },
    "details": {
        "merchantName": "2XU",
        "headlineRate": "3%",
        "rates": [{ "category": "General", "tier": "Standard", "rate": "3%", "description": "Standard Cashback 3%" }],
        "ratesUpdatedAt": "2026-03-27T05:50:44.571Z",
        "cashbackTerms": [{ "question": "Exclusions?", "answer": "You won't get Cashback on…" }],
        "categories": ["General"],
        "scrapedAt": "2026-06-23T09:00:00Z"
    },
    "tierUsed": "datacenter",
    "method": "browser",
    "costTelemetry": { "proxyBytes": 184320, "computeMs": 4200 },
    "error": null
}
```

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

#### Outcome fields

- `outcome` — `resolved` or `not_on_shopback`.
- `affiliate.status` — `network_identified` | `generic_affiliate` | `shopback_direct` | `click_out_failed` | `auth_expired` (session cookie no longer valid — re-paste `shopbackSessionCookie`).
- `resolvedVia` — `shopback_url` | `candidate` | `search` (how the merchant URL was found).

### Pricing & cost

This Actor uses **pay-per-event** pricing. A cheap `page-details` event covers detail extraction; per-tier `affiliate-direct` / `affiliate-datacenter` / `affiliate-residential` events price the click-out by the proxy tier that was actually needed (residential is charged only when cheaper tiers are blocked); `not-on-shopback` is a minimal charge. `details` runs are the cheapest, `both` adds the most value per run. Free-plan usage is supported within Apify's limits.

### Tips

- Pass a **domain** (not a ShopBack URL) and let the Actor resolve it — it cleans to the registrable domain and confirms the match, so you don't have to construct ShopBack URLs.
- Batch many targets in one run rather than one run per target.
- Use `mode: "details"` when you only need rates/terms — it stays on the cheapest tiers.

### FAQ & support

- **Is this legal?** The Actor reads publicly visible ShopBack pages and their click-out redirects. Respect ShopBack's Terms of Service and applicable laws; use the data responsibly.
- **A brand returns `not_on_shopback`** — it has no ShopBack merchant page for the selected region.
- **`click_out_failed`** — the page loaded but the click-out didn't fire after all escalation; retry on a later run.
- **`auth_expired`** — your ShopBack session cookie is no longer valid. Re-export and paste a fresh `shopbackSessionCookie` (include `sbrefresh`). Running on a schedule keeps the session alive and avoids this.
- Found a bug or need a custom variant (other cashback sources, full category crawl)? Use the **Issues** tab.

# Actor input Schema

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

affiliate = detect the active affiliate network via click-out; details = scrape the ShopBack merchant page; both = do both in one page load.

## `targets` (type: `array`):

Each target's 'input' is EITHER a company domain (e.g. 2xu.com) OR a ShopBack URL (e.g. shopback.com.au/2xu). Auto-detected and normalized. 'brand' is optional but improves domain->ShopBack resolution. 'rowNumber' is carried through untouched for sheet mapping.

## `region` (type: `string`):

Which ShopBack storefront to use when resolving domains.

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

Maximum parallel targets.

## `shopbackSessionCookie` (type: `string`):

<b>Needed only for <code>affiliate</code> / <code>both</code> modes</b> — ShopBack shows the click-out that reveals the affiliate network only when logged in. <code>details</code> mode needs no cookie. To get it (2 minutes, once): <b>1.</b> Log in to <a href='https://www.shopback.com.au' target='_blank'>shopback.com.au</a> in Chrome. <b>2.</b> Install the free <a href='https://chromewebstore.google.com/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm' target='_blank'>Cookie-Editor</a> extension. <b>3.</b> On the ShopBack tab, open Cookie-Editor → Export → JSON (copies to clipboard). <b>4.</b> Paste the JSON here. It must include the <code>sbrefresh</code> cookie (it will, if you're logged in). Stored encrypted, never logged. The session self-refreshes as long as you run the Actor regularly (e.g. a weekly schedule); if it ever dies, results say <code>auth\_expired</code> — just re-paste.

## `forceBrowser` (type: `boolean`):

Skip the HTTP fast path and always use the Playwright browser path. (Reserved: the HTTP fast path is enabled post-recon once a replayable click-out / JSON detail endpoint is confirmed.)

## Actor input object example

```json
{
  "mode": "details",
  "targets": [
    {
      "input": "2xu.com",
      "brand": "2XU",
      "rowNumber": 137
    }
  ],
  "region": "au",
  "maxConcurrency": 5,
  "forceBrowser": false
}
```

# Actor output Schema

## `results` (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": "details",
    "targets": [
        {
            "input": "2xu.com",
            "brand": "2XU",
            "rowNumber": 137
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation_craft/affiliate-network-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 = {
    "mode": "details",
    "targets": [{
            "input": "2xu.com",
            "brand": "2XU",
            "rowNumber": 137,
        }],
}

# Run the Actor and wait for it to finish
run = client.actor("automation_craft/affiliate-network-detector").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 '{
  "mode": "details",
  "targets": [
    {
      "input": "2xu.com",
      "brand": "2XU",
      "rowNumber": 137
    }
  ]
}' |
apify call automation_craft/affiliate-network-detector --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=automation_craft/affiliate-network-detector",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/ZjqcYXJTs1L3BdwAL/builds/KXNQvSpfC7xpeJLnT/openapi.json
