# Tech Stack Lead Finder: Shopify, Klaviyo & 120+ Technologies (`m_ctim/tech-stack-lead-finder`) Actor

Find websites by the technology they use and turn them into leads. Checks each domain for 125 technologies (Shopify, WooCommerce, Klaviyo, HubSpot, Intercom, Stripe...), keeps sites matching your stack filters, and adds the emails, phones and social profiles they publish.

- **URL**: https://apify.com/m\_ctim/tech-stack-lead-finder.md
- **Developed by:** [Timothy Kelvin](https://apify.com/m_ctim) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

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

## Tech Stack Lead Finder: Shopify, Klaviyo & 120+ Technologies

Give it a list of domains. It checks each homepage for **124 technologies** (ecommerce platforms, email and SMS marketing, analytics, live chat, payments, reviews, A/B testing, CMS, frameworks, hosting), keeps only the sites that match the stack you're looking for, and adds the **business emails, phone numbers and social profiles those sites publish**. The result is a lead list you can use straight away.

Typical searches:

- Shopify stores **not** using Klaviyo (an email tool's prospects)
- WooCommerce or BigCommerce stores using Klarna or Afterpay
- Sites running Intercom or Drift (a chat competitor's prospects)
- Stores on Shopify with Yotpo reviews but no Attentive SMS

### Who it's for

- **SaaS sales and agencies** building prospect lists by technology: "stores on X without Y".
- **App and plugin makers** finding stores on a platform to pitch an integration.
- **Market researchers** measuring who uses what across a list of domains.

### How it works

1. **Detect.** One request per domain, to the homepage. Technologies are recognised from response headers, cookies, meta tags, script and stylesheet URLs, and page markup.
2. **Filter.** `requireAll`, `requireAny` and `exclude` decide which sites are matches.
3. **Enrich (matches only).** At most two more pages: the contact page (the site's own "Contact" link, or `/contact`) and the about page. Emails, phone numbers and social links are read from those and the homepage.

robots.txt is checked before every page. Sites behind a bot wall (a Cloudflare challenge, Vercel checkpoint and the like) are reported as `blocked` and skipped; the actor never tries to get around them. No proxies, no browser, no logins.

### Input examples

The default: 10 real domains, keeping the Shopify stores (5 match).

```json
{
  "domains": ["allbirds.com", "colourpop.com", "kyliecosmetics.com", "brooklinen.com", "skullcandy.com",
              "wordpress.org", "woocommerce.com", "basecamp.com", "ghost.org", "prestashop.com"],
  "requireAny": ["Shopify"]
}
```

Shopify stores that don't use Klaviyo:

```json
{
  "domains": ["allbirds.com", "colourpop.com", "kyliecosmetics.com", "brooklinen.com", "skullcandy.com"],
  "requireAll": ["Shopify"],
  "exclude": ["Klaviyo"]
}
```

Any store platform with buy-now-pay-later, and a record of every site checked:

```json
{
  "domains": ["..."],
  "requireAny": ["Shopify", "WooCommerce", "BigCommerce", "Magento"],
  "requireAll": ["Klarna"],
  "includeNonMatches": true
}
```

### Input fields

| Field | What it does |
|---|---|
| `domains` | Domains or URLs, one per line. Only the domain is used. |
| `requireAll` | Site must use every one of these. |
| `requireAny` | Site must use at least one of these. |
| `exclude` | Site must use none of these. |
| `enrich` | Read contact and about pages for emails, phones and socials. On by default. |
| `includeNonMatches` | Also output non-matching and unreachable sites, with the reason. Free. |
| `maxItems` | Stop after this many matching sites. |

Technology names are forgiving (`woocommerce`, `Google Analytics`, `GA4`, `nextjs` all work). A misspelt name stops the run with the list of valid names, so a typo never silently matches nothing. With no filters at all, every site that loads counts as a match.

### Output

A real row from the default run (2026-09-26):

```json
{
  "domain": "brooklinen.com",
  "matched": true,
  "status": "ok",
  "technologies": [
    { "name": "Shopify", "category": "ecommerce", "confidence": "high", "evidence": "header: powered-by: Shopify" },
    { "name": "Google Analytics", "category": "analytics", "confidence": "medium", "evidence": "script: googletagmanager.com/gtag/js" },
    { "name": "Yotpo", "category": "reviews", "confidence": "medium", "evidence": "html: cdn-widgetsrepository.yotpo.com" },
    { "name": "Cloudflare", "category": "cdn-hosting", "confidence": "high", "evidence": "header: cf-ray" },
    { "name": "OneTrust", "category": "consent", "confidence": "medium", "evidence": "script: cdn.cookielaw.org" }
  ],
  "matchedFilters": { "requireAll": [], "requireAny": ["Shopify"], "excluded": [] },
  "emails": ["hello@brooklinen.com", "press@brooklinen.com", "sales@brooklinenbusiness.com", "influencer@brooklinen.com"],
  "phones": ["646-798-7447"],
  "socials": {
    "facebook": "https://www.facebook.com/Brooklinen",
    "x": "https://x.com/brooklinen",
    "instagram": "https://www.instagram.com/brooklinen"
  },
  "title": "Luxury Bedding, Sheets & Comforters Online | Brooklinen",
  "description": "Discover Brooklinen’s premium bedding collection. Shop soft sheets, cozy comforters, and soft & firm supportive pillows designed for the best night’s sleep.",
  "language": "en",
  "httpStatus": 200,
  "pagesChecked": [
    { "url": "https://brooklinen.com/", "result": "ok" },
    { "url": "https://www.brooklinen.com/pages/contact", "result": "ok" },
    { "url": "https://www.brooklinen.com/pages/about", "result": "ok" }
  ],
  "sourceUrl": "https://www.brooklinen.com/",
  "scrapedAt": "2026-09-26T00:35:08.040Z"
}
```

#### Confidence

| Level | Based on |
|---|---|
| `high` | A response header, cookie or generator meta tag the technology sets (e.g. Shopify's `powered-by` header) |
| `medium` | A script or stylesheet loaded from the technology's own domain (e.g. `static.klaviyo.com`) |
| `low` | A weaker markup hint |

`evidence` shows exactly what was matched, so you can check any detection.

#### Contact details

- **Emails** come from `mailto:` links and the visible page text, including spellings like `info [at] domain [dot] com`. Role addresses (`info@`, `sales@`, `hello@`, `support@`...) are listed first. Addresses are never guessed or generated: if a site only offers a contact form or a help desk on another domain, `emails` is empty.
- **Phones** come from `tel:` links and numbers in an unambiguous format (international `+` numbers, or North American `(xxx) xxx-xxxx` / `xxx-xxx-xxxx`). Order numbers, dates and prices are not mistaken for phones.
- **Socials**: the site's own LinkedIn company page, X, Instagram, Facebook, YouTube and TikTok profiles. Share buttons and individual posts are ignored.
- **Language** is the page's declared language (`<html lang>`).

#### Status values

`ok`, `blocked` (bot protection page), `robots_disallowed`, `unreachable` (DNS or connection failure), `not_found`, `server_error`, `rate_limited`. Non-`ok` sites never match and are only output with `includeNonMatches`.

### What it detects

Ecommerce (Shopify, WooCommerce, BigCommerce, Magento, Salesforce Commerce Cloud, PrestaShop, Shopware, Ecwid, OpenCart), email and SMS marketing (Klaviyo, Mailchimp, Omnisend, Brevo, Kit, Drip, MailerLite, Constant Contact, Attentive, Postscript, Privy), marketing automation (HubSpot, Marketo, Pardot, ActiveCampaign, Customer.io), analytics and pixels (Google Analytics, Tag Manager, Meta, TikTok, Pinterest, LinkedIn, X and Snap pixels, Hotjar, Clarity, Segment, Mixpanel, Amplitude, Heap, PostHog, FullStory, Plausible, Fathom, Matomo), live chat (Intercom, Drift, Crisp, Tawk.to, Zendesk, LiveChat, Tidio, Gorgias, Olark, Freshchat, Help Scout), payments (Stripe, PayPal, Shop Pay, Klarna, Afterpay, Affirm, Sezzle, Square, Braintree, Amazon Pay), reviews (Yotpo, Judge.me, Okendo, Trustpilot, Stamped, Loox, REVIEWS.io, Bazaarvoice), A/B testing (Optimizely, VWO, AB Tasty, Convert, Kameleoon, LaunchDarkly), CMS (WordPress, Drupal, Joomla, Wix, Squarespace, Webflow, Ghost, HubSpot CMS, Framer, Contentful, Sanity, Weebly, Craft CMS, TYPO3), frameworks (Next.js, Nuxt, Gatsby, Remix, Astro, SvelteKit, React, Vue.js, Angular, jQuery, Alpine.js, Tailwind CSS, Bootstrap), hosting and CDN (Cloudflare, Vercel, Netlify, CloudFront, Fastly, Akamai, GitHub Pages, Heroku, Fly.io, Render), search (Algolia, Klevu, Searchspring), consent (OneTrust, Cookiebot), subscriptions and loyalty (Recharge, Smile.io).

Detection reads the homepage as served, so tools loaded only after a click or on other pages (a checkout script, a chat widget injected late by a tag manager) can be missed.

### FAQ

**Where do I get domains?** Your CRM, a conference exhibitor list, a directory export, or another actor's output. This actor checks the domains you give it; it doesn't discover new ones.

**How fast is it?** About 1 to 3 seconds per domain, five domains at a time, one request per second per site.

**Is the contact data legal to use?** It's what each business publishes on its own site for people to contact it. How you use it (cold email rules like CAN-SPAM, GDPR and PECR) is your responsibility.

### Pricing

Pay per matching site only. Non-matching, blocked and unreachable sites are free.

### Disclaimer

This actor is unofficial and is not affiliated with, endorsed by, or connected to BuiltWith, Wappalyzer, Shopify or any technology vendor or website it detects. Trademarks belong to their owners.

# Actor input Schema

## `domains` (type: `array`):

One per line: example.com, www.example.com or a full URL (only the domain is used). Each homepage is fetched once.

## `requireAll` (type: `array`):

Keep only sites using every one of these, e.g. "Shopify", "Klaviyo". Names are forgiving: "woocommerce", "google analytics", "GA4" all work.

## `requireAny` (type: `array`):

Keep only sites using at least one of these, e.g. "Shopify", "WooCommerce", "BigCommerce".

## `exclude` (type: `array`):

Drop sites using any of these. Example: require Shopify and exclude Klaviyo to find stores without Klaviyo.

## `enrich` (type: `boolean`):

For matching sites, read the contact and about pages (at most 2 extra pages) for published emails, phone numbers and social profiles.

## `includeNonMatches` (type: `boolean`):

Also output sites that didn't match, or couldn't be loaded, with the reason. These rows are free.

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

Stop once this many matching sites have been found.

## Actor input object example

```json
{
  "domains": [
    "allbirds.com",
    "colourpop.com",
    "kyliecosmetics.com",
    "brooklinen.com",
    "skullcandy.com",
    "wordpress.org",
    "woocommerce.com",
    "basecamp.com",
    "ghost.org",
    "prestashop.com"
  ],
  "requireAny": [
    "Shopify"
  ],
  "enrich": true,
  "includeNonMatches": false,
  "maxItems": 1000
}
```

# 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 = {
    "domains": [
        "allbirds.com",
        "colourpop.com",
        "kyliecosmetics.com",
        "brooklinen.com",
        "skullcandy.com",
        "wordpress.org",
        "woocommerce.com",
        "basecamp.com",
        "ghost.org",
        "prestashop.com"
    ],
    "requireAny": [
        "Shopify"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("m_ctim/tech-stack-lead-finder").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 = {
    "domains": [
        "allbirds.com",
        "colourpop.com",
        "kyliecosmetics.com",
        "brooklinen.com",
        "skullcandy.com",
        "wordpress.org",
        "woocommerce.com",
        "basecamp.com",
        "ghost.org",
        "prestashop.com",
    ],
    "requireAny": ["Shopify"],
}

# Run the Actor and wait for it to finish
run = client.actor("m_ctim/tech-stack-lead-finder").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 '{
  "domains": [
    "allbirds.com",
    "colourpop.com",
    "kyliecosmetics.com",
    "brooklinen.com",
    "skullcandy.com",
    "wordpress.org",
    "woocommerce.com",
    "basecamp.com",
    "ghost.org",
    "prestashop.com"
  ],
  "requireAny": [
    "Shopify"
  ]
}' |
apify call m_ctim/tech-stack-lead-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,m_ctim/tech-stack-lead-finder"
        }
    }
}
```

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/BeFRzVLf173892vT2/builds/1eQmhDMs4b8mb02kD/openapi.json
