Signal Detection

This guide walks through how to use the signals server to qualify accounts. It covers when to use detect_signal vs. individual detectors, how to tune set_signals_order, and how to interpret each signal.

When to use detect_signal

detect_signal is the recommended entry point. It dispatches every detector in the configured order and returns the union of fired signals. Dispatch is free — only the detectors that actually run are charged.

$curl -X POST https://api.gtm-tools.sh/api/v0/detect_signal \
> -H "Authorization: Bearer $GTM_TOOLS_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{"domain": "gymshark.com", "techs": ["zendesk.com", "intercom.com"]}'

Use detect_signal when:

  • You’re qualifying a fresh list of domains and want every available signal.
  • You want a single round-trip per company.
  • You haven’t yet figured out which signals matter most for your ICP.

Use individual detectors when:

  • You only care about one specific signal (e.g. you only sell to companies hiring SDRs).
  • You want to short-circuit on the first hit and avoid running the rest.
  • You’re A/B testing detector ordering.

Configure detector order

set_signals_order controls the order detectors run inside detect_signal. Front-load the cheapest, highest-precision signals so you can act on the first hit.

$curl -X POST https://api.gtm-tools.sh/api/v0/set_signals_order \
> -H "Authorization: Bearer $GTM_TOOLS_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "order": [
> "signal_hiring_sales_rep_repost",
> "signal_trustpilot_negative_support_reviews",
> "signal_hiring_support",
> "signal_socials_spike",
> "signal_technologies_identified"
> ]
> }'

View the current order any time:

$curl https://api.gtm-tools.sh/api/v0/get_signals_order \
> -H "Authorization: Bearer $GTM_TOOLS_API_KEY"

Signal interpretation

Hiring signals

SignalStrengthWhat it means
signal_hiring_sales_rep_repostHighestSame SDR/BDR role posted multiple times — previous hire churned. Strong urgency.
signal_hiring_sales_leadershipHighNew head of sales coming in — budget reset, openness to new vendors.
signal_hiring_supportMediumSupport team scaling — likely operational pain.
signal_hiring_sales_repMediumStandard sales hiring — pipeline-building mode.
signal_hiring_roleVariableWhatever role you specified — calibrate to your ICP.

Trustpilot signals

SignalStrengthWhat it means
signal_trustpilot_negative_support_reviewsHighestCustomers actively complaining about support. Active churn risk.
signal_trustpilot_negative_reviewsMediumGeneral dissatisfaction — broader pain.
signal_trustpilot_positive_reviewsReverse signalDon’t pitch support tooling — they’re doing fine.

Negative-support reviews are uniquely actionable: the customer is pre-qualified, the pain is named, and you can quote the review in your outreach.

Marketing signals

SignalStrengthWhat it means
signal_socials_spikeMediumSustained Instagram/TikTok follower growth — marketing momentum + likely funded.

Tech-stack signals

signal_technologies_identified is the only signal that needs configuration up-front. Pass techs as an array of identifiers to match against the website.

$curl -X POST https://api.gtm-tools.sh/api/v0/signal_technologies_identified \
> -H "Authorization: Bearer $GTM_TOOLS_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "domain": "gymshark.com",
> "techs": ["zendesk.com", "intercom.com", "gorgias.com", "freshdesk.com"]
> }'
1{
2 "domain": "gymshark.com",
3 "matched": ["zendesk.com"],
4 "evidence": [{ "tech": "zendesk.com", "source": "html", "snippet": "..." }]
5}

This is how you confirm a prospect is on the competitive stack you displace.

Scoring + ranking

The signals server returns raw fires; ranking is your job. A simple weighted score:

1const WEIGHTS: Record<string, number> = {
2 signal_hiring_sales_rep_repost: 5,
3 signal_trustpilot_negative_support_reviews: 4,
4 signal_hiring_support: 3,
5 signal_socials_spike: 2,
6 signal_technologies_identified: 2,
7 signal_hiring_role: 1,
8};
9
10function score(detected: { name: string; fired: boolean }[]): number {
11 return detected
12 .filter(s => s.fired)
13 .reduce((acc, s) => acc + (WEIGHTS[s.name] ?? 1), 0);
14}

Then sort target accounts by score and prospect top-down.

Token budget

A full detect_signal run with all 9 priced detectors firing costs 45 tokens (9 × 5). In practice, most companies trigger 2–4 signals, putting the median around 15 tokens per account. That’s $0.15 per qualification.

Next steps