---
name: competitor-tech-churn-outbound
description: "Watch target accounts for added or dropped competitor tools with BuiltWith data in Clay, then launch timed outbound and keep a tech baseline in your CRM. Use when a target account drops a competitor or adds a tool that pairs with yours, there is a short window to start a conversation, but static tech stack lists only show what is installed today, not what changed."
---

# Launch Outbound When Target Accounts Add or Drop a Competitor

When a target account drops a competitor or adds a tool that pairs with yours, there is a short window to start a conversation, but static tech stack lists only show what is installed today, not what changed.

## When to use this skill

- The user wants to set up or run this workflow: "Launch Outbound When Target Accounts Add or Drop a Competitor".
- The user describes this problem: When a target account drops a competitor or adds a tool that pairs with yours, there is a short window to start a conversation, but static tech stack lists only show what is installed today, not what changed.

## At a glance

- Category: Outbound
- Difficulty: Advanced
- Time saved: 3 hours per week. This figure is an estimate, not a measured result.

## Tools

Options separated by "or" are alternatives; use whichever the user already has.

- Clay
- BuiltWith or HG Insights
- HubSpot or Salesforce
- Apollo
- Instantly or Smartlead

## Steps

1. List the technologies that matter: direct competitors, tools that pair well with yours, and tools your product replaces, keeping in mind that website-based detection such as BuiltWith only sees tools that leave a footprint on the site (tags, widgets, scripts)
2. Export target accounts from HubSpot or Salesforce monthly with domain, owner, CRM ID, and the technology list saved last month, and upload them to Clay; leave the list empty on the first run to save a baseline
3. Pull the current technology list for each domain with a technographic provider in your Clay workspace, such as BuiltWith, or HG Insights where you have access, and compare it with last month, using first-detected and last-detected dates when the provider returns them
4. Classify each change as dropped a competitor, added a competitor, or added a complementary tool, and skip accounts with no relevant change, current customers, and open deals
5. For changed accounts, find one to three people in the buying role with Apollo or a Clay waterfall, write an opener that relates to the change category without saying how you know or guessing why they changed, and add them to an Instantly or Smartlead sequence sent from the account owner
6. Write the new technology list, the change type, and the date back to the CRM company record so next month compares against it, and create a task for the owner on accounts that changed

## Template outline

Field names, thresholds, and message text are starting points to adapt.

~~~text
Clay Workflow (CSV trigger, monthly account export):
1. Input: company_domain, company_name, crm_company_id, owner_email, previous_technologies, target_title
2. Technographic lookup (e.g. BuiltWith): current_technologies, first and last detected dates where returned
3. AI compare against your lists:
   - Competitors: {{your_competitor_list}}
   - Complements: {{your_complement_list}}
   - change_type: dropped_competitor, added_competitor, added_complement, or none
   - Empty previous list: none (baseline run)
4. IF change_type != none AND not a customer or open deal:
   - Find 1 to 3 contacts in {{target_title}} (Apollo or waterfall), verify emails
   - Opener by change type, never "we noticed you removed X"
   - Sequencer: add lead with opener, change_type, owner as sender
   - CRM task for owner: "{{company_name}}: {{change_type}} ({{tool}})"
5. CRM update (every account): detected technologies, last technology change, date
Output: a monthly list of accounts whose stack changed in a way that matters to you, with contacts in a timed sequence and an updated baseline in the CRM
~~~

## Optional: build it with the Clay CLI

This builds the play as a Clay workflow with a CSV trigger. Each account row becomes one run: pull the current technology list, compare it with last month, find a contact when something relevant changed, add them to a sequence, and write the new list back to the CRM for next month. The Clay CLI cannot create tables, so this build uses a workflow. Website-based detection only sees tools that leave a footprint on the site, so treat a missing tool as "not detected", not "removed", unless your provider returns a last-detected date.

Written against Clay CLI v1.3.1. Run these commands only in the user's own Clay workspace, logged in with their own account, after they confirm. Items marked VERIFY are config shapes the CLI help does not document; check them in the workspace before relying on them.

### Prerequisites

- Install the Clay CLI: Use version 1.3.1 or later, installed from Clay's own instructions. This page does not include an install command because the CLI reference it was written from does not list one. You also need jq, which the script uses to read the JSON the CLI prints.
- Log in to your workspace: Browser login is the default. Use the device flow on a headless machine. A static key in the CLAY_API_KEY environment variable also works. Workflow commands need the terracotta:cli scope, so an auth error that names it means your login cannot manage workflows.
  - Log in with a browser: `clay login`
  - Log in on a headless machine: `clay login --device`
  - Confirm who you are logged in as: `clay whoami`
- Pick the workspace to build in: The workflow is created in your active workspace. Switch first if you belong to more than one.
  - List workspaces: `clay workspaces list`
  - Show the active workspace: `clay workspaces current`
  - Switch workspace: `clay workspaces switch <workspaceId>`
- Find your action keys: Action package ids and keys are specific to your workspace. Save the catalog, search it for a technographic lookup (for example BuiltWith), an AI text action, a find-people action, your sequencer, and your CRM update action, then paste their ids into the top of the script. Skip "clay workflows actions test": it spends credits.
  - Save the action catalog: `clay workflows actions list > catalog.json`
  - Search the catalog: `grep -Eio '"[^"]*(builtwith|technolog|hg insights|use ai|generate|find people|apollo|instantly|smartlead|hubspot|salesforce)[^"]*"' catalog.json | sort -u`
  - See an action's inputs and outputs: `clay workflows actions schema <packageId> <actionKey>`
- Write your tool lists and add the CRM fields: List your direct competitors and the tools that pair well with yours, using the names your technographic provider returns. Add company properties for detected technologies and last technology change in HubSpot or Salesforce, so each month compares against the last.
- Connect your sequencer and make a test campaign: Connect Instantly or Smartlead inside Clay and create an empty campaign for testing, so early runs do not land in a live sequence.

### Workflow: Technology change outbound

Trigger (csv_upload): You upload your target accounts monthly with the technology list saved last month. Each header becomes a string input, and each row becomes one run once the workflow is published. VERIFY: The trigger type string "csv_upload" is inferred. The CLI help does not show how to create a CSV trigger.

Inputs (CSV headers):

- company_domain: Account domain (example: example.com)
- company_name: Account name (example: Example Co)
- crm_company_id: Company ID in your CRM (example: 1234567890)
- owner_email: Account owner (example: owner@yourdomain.com)
- previous_technologies: Last month's list, separated by semicolons (example: Google Analytics; Intercom; CompetitorX)
- target_title: Buying role to contact (example: Head of Customer Support)

1. Pull current technologies (action): Looks up the technologies currently detected on the domain, with first-detected and last-detected dates where the provider returns them.
   - Inputs: company_domain
   - Outputs: current_technologies
   - VERIFY: Which technographic providers you can use depends on your Clay workspace and plan. BuiltWith detects website technologies; HG Insights-style install data, where available to you, can cover tools that do not show on the site.
2. Classify the change and write an opener (action): An AI text action compares the two lists against your competitor and complement lists and returns the change type, the tool, and an opener.
   - Inputs: company_domain, previous_technologies, current_technologies, target_title
   - Outputs: change_type, tool, opener
   - Prompt:

~~~text
Compare two technology lists for {{company_domain}}.
Last month: {{previous_technologies}}
Now: {{current_technologies}}
Competitors: {{your_competitor_list}}
Complementary tools: {{your_complement_list}}
Return JSON with change_type (dropped_competitor, added_competitor, added_complement, or none), tool (the tool that changed, or empty), and opener (one sentence under 25 words for a cold email to a {{target_title}} that relates to the change category).
If last month's list is empty, return change_type none.
The opener must not say how the change was detected or claim to know why they changed. No em dashes.
~~~

3. Find the contact (action): Finds one person in the target role at the account, with a work email. Runs only when change_type is not none.
   - Inputs: company_domain, target_title
   - Outputs: first_name, last_name, title, email
   - VERIFY: One run handles one contact. The "changed" rule needs a run condition, which the CLI help does not document, so set it in the Clay UI. Skip customers and open deals before uploading, or add a CRM lookup step.
4. Add to the sequence (action): Adds the contact to your Instantly or Smartlead campaign with the opener, change type, and owner as custom fields.
   - Inputs: email, first_name, last_name, company_name, opener, change_type, owner_email
   - Outputs: Sequencer lead
5. Save the new list to the CRM (action): Writes the current technology list, the change type, and the date to the company record so next month compares against it. Runs for every account.
   - Inputs: crm_company_id, current_technologies, change_type
   - Outputs: CRM record

### Script: build-tech-change-outbound.sh

Creates the workflow, the CSV trigger, and five steps, then pauses so you can map step inputs and the change condition. It validates the graph, offers one test run, and asks before publishing.

~~~bash
#!/usr/bin/env bash
# Builds the "Technology change outbound" Clay workflow
# in YOUR Clay workspace, using YOUR Clay CLI login.
# Written against Clay CLI v1.3.1. Not run or tested by GTM Playbooks.
# Lines tagged VERIFY use a shape the CLI help does not document.
set -euo pipefail

# Copy these from catalog.json (see "Find your action keys").
TECH_PACKAGE_ID=""      # BuiltWith or another technology lookup
TECH_ACTION_KEY=""
CLASSIFY_PACKAGE_ID=""  # Use AI or another AI text action
CLASSIFY_ACTION_KEY=""
CONTACT_PACKAGE_ID=""   # Find people at a company (by title)
CONTACT_ACTION_KEY=""
SEQUENCER_PACKAGE_ID="" # Instantly or Smartlead: add lead to campaign
SEQUENCER_ACTION_KEY=""
CRM_PACKAGE_ID=""       # HubSpot or Salesforce: update company
CRM_ACTION_KEY=""

# One input to test before real traffic. Use yourself or a teammate.
TEST_ROW='{"company_domain":"","company_name":"","crm_company_id":"","owner_email":"","previous_technologies":"","target_title":""}'

for v in TECH_PACKAGE_ID TECH_ACTION_KEY CLASSIFY_PACKAGE_ID CLASSIFY_ACTION_KEY CONTACT_PACKAGE_ID CONTACT_ACTION_KEY SEQUENCER_PACKAGE_ID SEQUENCER_ACTION_KEY CRM_PACKAGE_ID CRM_ACTION_KEY; do
  [[ -n "${!v}" ]] || { echo "Set $v at the top of this script." >&2; exit 1; }
done
command -v clay > /dev/null || { echo "Clay CLI not found on PATH." >&2; exit 1; }
command -v jq > /dev/null || { echo "jq is required to read CLI output." >&2; exit 1; }
clay whoami > /dev/null || { echo "Not logged in. Run: clay login" >&2; exit 1; }

# VERIFY: only "workflows create" documents an "id" field in its output.
read_id() {
  local id
  id=$(jq -r '.id // empty' "$1")
  [[ -n "$id" ]] || { echo "No id found in $1. Open it and adjust read_id." >&2; exit 1; }
  echo "$id"
}

mkdir -p clay-tech-change-outbound
cd clay-tech-change-outbound

echo "1/9 Create the workflow"
clay workflows create --name "Technology change outbound" > workflow.json
WF_ID=$(read_id workflow.json)
WF_URL=$(jq -r '.url // empty' workflow.json)

echo "2/9 Add the CSV upload trigger"
# VERIFY: triggerType "csv_upload" is inferred; the help does not show it.
clay workflows triggers create "$WF_ID" --input '{"triggerType":"csv_upload"}' > trigger.json
TRG_ID=$(read_id trigger.json)

echo "3/9 Step 1: pull current technologies"
# VERIFY: help shows nodeType and name only; actionPackageId and actionKey are a guess.
STEP1=$(jq -nc --arg p "$TECH_PACKAGE_ID" --arg k "$TECH_ACTION_KEY" '{nodeType: "tool", name: "Pull current technologies", actionPackageId: $p, actionKey: $k}')
clay workflows nodes create "$WF_ID" --input "$STEP1" > step1.json
STEP1_ID=$(read_id step1.json)

echo "4/9 Step 2: classify the change and write an opener"
# VERIFY: action fields inside "step" are inferred from the documented utility example.
STEP2=$(jq -nc --arg n "$STEP1_ID" --arg p "$CLASSIFY_PACKAGE_ID" --arg k "$CLASSIFY_ACTION_KEY" '{target: {type: "after-node", nodeId: $n}, step: {kind: "action", actionPackageId: $p, actionKey: $k}}')
clay workflows nodes insert "$WF_ID" --input "$STEP2" > step2.json
STEP2_ID=$(read_id step2.json)

echo "5/9 Step 3: find the contact"
# VERIFY: same inferred insert shape as step 2.
STEP3=$(jq -nc --arg n "$STEP2_ID" --arg p "$CONTACT_PACKAGE_ID" --arg k "$CONTACT_ACTION_KEY" '{target: {type: "after-node", nodeId: $n}, step: {kind: "action", actionPackageId: $p, actionKey: $k}}')
clay workflows nodes insert "$WF_ID" --input "$STEP3" > step3.json
STEP3_ID=$(read_id step3.json)

echo "6/9 Step 4: add to the sequence"
# VERIFY: same inferred insert shape as step 2.
STEP4=$(jq -nc --arg n "$STEP3_ID" --arg p "$SEQUENCER_PACKAGE_ID" --arg k "$SEQUENCER_ACTION_KEY" '{target: {type: "after-node", nodeId: $n}, step: {kind: "action", actionPackageId: $p, actionKey: $k}}')
clay workflows nodes insert "$WF_ID" --input "$STEP4" > step4.json
STEP4_ID=$(read_id step4.json)

echo "7/9 Step 5: save the new list to the crm"
# VERIFY: same inferred insert shape as step 2.
STEP5=$(jq -nc --arg n "$STEP4_ID" --arg p "$CRM_PACKAGE_ID" --arg k "$CRM_ACTION_KEY" '{target: {type: "after-node", nodeId: $n}, step: {kind: "action", actionPackageId: $p, actionKey: $k}}')
clay workflows nodes insert "$WF_ID" --input "$STEP5" > step5.json
clay workflows graph get "$WF_ID" --mode full > graph.json

echo "8/9 Map step inputs"
cat <<EOF

Step inputs are specific to your workspace. Map them before validating:
  Step 1 tech:      company_domain
  Step 2 classify:  previous_technologies, current list from step 1,
                    target_title, and the prompt with your tool lists
  Step 3 contact:   company_domain and target_title; add a run condition
                    so steps 3 and 4 only run when change_type is not none
  Step 4 sequencer: email, name, company, opener, change_type, owner
  Step 5 CRM:       crm_company_id, current list, change_type, today
Map them in the Clay UI${WF_URL:+ at $WF_URL}, or per node with:
  clay workflows nodes get $WF_ID <nodeId>
  clay workflows nodes update $WF_ID <nodeId> --input node.json
graph.json in this folder shows the current nodes and edges.

EOF
read -r -p "Press Enter when inputs are mapped. "

echo "9/9 Validate, test once, publish"
clay workflows graph validate "$WF_ID"
clay workflows diagram "$WF_ID"

if jq -e 'all(.[]; . != "")' <<< "$TEST_ROW" > /dev/null; then
  read -r -p "Run TEST_ROW once? It can spend Clay credits, add a lead to your sequencer, and update your CRM. [y/N] " answer
  if [[ "$answer" == [yY] ]]; then
    clay workflows runs test "$WF_ID" --inputs "$TEST_ROW" > test-run.json
    echo "Saved test-run.json. Check each step with: clay workflows runs steps $WF_ID <runId>"
  fi
else
  echo "TEST_ROW is empty, skipping the test run."
fi

read -r -p "Publish the workflow now? [y/N] " answer
if [[ "$answer" == [yY] ]]; then
  clay workflows publish "$WF_ID" --name v1
fi

echo "Workflow $WF_ID, CSV upload trigger $TRG_ID. All responses are saved in $(pwd)."
~~~

### Account CSV: accounts.csv

~~~csv
company_domain,company_name,crm_company_id,owner_email,previous_technologies,target_title
example.com,Example Co,1234567890,owner@yourdomain.com,Google Analytics; Intercom; CompetitorX,Head of Customer Support
~~~

### Run it on your accounts

After publishing, upload the CSV to the trigger and start with a few rows. Each row is one run.

- Load the saved ids (run inside clay-tech-change-outbound/): `WF_ID=$(jq -r '.id' workflow.json); TRG_ID=$(jq -r '.id' trigger.json)`
- Upload the CSV (this does not start runs): `clay workflows triggers csv upload "$TRG_ID" --file accounts.csv`
- Run the first 5 rows (needs a published workflow, one run per row): `clay workflows triggers csv run "$TRG_ID" --limit 5`
- List runs: `clay workflows runs list "$WF_ID"`
- Inspect one run: `clay workflows runs get "$WF_ID" <runId>`
- See each step's output for that run: `clay workflows runs steps "$WF_ID" <runId>`

### Verify in the workspace

- The CSV trigger type "csv_upload" is inferred. If "triggers create" exits with code 2 (validation), check which trigger types your workspace accepts.
- The help documents "nodes create" with nodeType and name only. If it rejects actionPackageId and actionKey, create the node with a name only and pick the action in the Clay UI.
- The reference says action steps take actionPackageId and actionKey but shows only a utility example for "nodes insert", so the placement of those fields inside "step" is inferred.
- Only "workflows create" documents an id field in its response. The script reads .id from trigger and node responses too and stops if it is missing.
- Package ids and action keys differ by workspace and depend on which integrations you have connected. Copy them from your catalog; this page does not guess them.
- Step input mapping is dynamic per workspace. The CLI path is "nodes get" then "nodes update", where incomingEdges is a full replacement. The argument order for "nodes get" is inferred from "nodes update".
- The help does not say whether step 1 connects to the trigger automatically. "clay workflows graph validate" reports a disconnected graph.
- Technology names must match between your lists and the provider output. Check a few lookups by hand before trusting the classification.
- "runs test" without --live is assumed to run the draft. The reference lists --live without describing it.
- Workflow runs can spend Clay credits and write to connected tools. Exit code 3 means re-run clay login, and exit code 4 means you are rate limited (wait for details.retryAfter).

## Guardrails

- Work only in the user's own accounts and workspaces, with their credentials.
- Confirm with the user before any step that writes to a CRM, sends email or messages, spends credits, or moves money.
- Treat every hours, cost, and threshold figure as a starting assumption and replace it with the user's numbers.
- Do not invent data, prices, or results. If a vendor price matters, check the vendor's current pricing page.

## Source

https://gtmplaybooks.io/playbooks/competitor-tech-churn-outbound/
