mirror of
https://github.com/superdesigndev/treg.git
synced 2026-10-02 03:24:35 +08:00
Merge pull request #749 from superdesigndev/feat/gtm-engineering-hub
feat(web): the GTM engineering playbook at /gtm-engineering
This commit is contained in:
@@ -36,6 +36,7 @@ sources:
|
||||
- src/treg/web/usecase-ads.html
|
||||
- src/treg/web/people-search.html
|
||||
- src/treg/web/leads-signals.html
|
||||
- src/treg/web/gtm-engineering.html
|
||||
- src/treg/web/grokbot.html
|
||||
- src/treg/web/fable-gtm.html
|
||||
- src/treg/web/ugc.html
|
||||
@@ -127,6 +128,7 @@ server-side first-touch attribution across signup, first successful call and top
|
||||
| `/resources` + `/use-cases/<slug>` | The outcome pages and their hub. Their sitemap rows are spread from `_USE_CASES` rather than listed by hand, so routing a new page lists it — see below. |
|
||||
| `/blog` + `/blog/people-search-bench` | A thin, hand-kept index of the launch pages (`_BLOG_LAUNCHES`, newest first, dated by the day each route shipped) and short posts (`_BLOG_POSTS`); the bench post repeats the four People Search Bench scores from `/grokbot#bench` and links there. Each post carries `BlogPosting` schema from `_blog_posting_ld` (headline, the `_BLOG_POSTS` date as published and modified, a named `Person` author, treg.to as publisher) beside its breadcrumbs, because a dated, bylined article earns the validation click and the AI citation where a bare page does not. Both are `_page()`-rendered, hosted-only, sitemapped (0.7 / 0.6) and in the route manifest. `/agents/grok-bot` (and `.md`) 301 to `/grokbot`: the launch page is the destination, the agent page was never linked as one, and the sitemap lists only `/grokbot`. |
|
||||
| `/people-search` + `/leads-signals` + `/grokbot` + `/fable` + `/ugc` | The launch-campaign landings, bundled files served by their own routes through `_static_page` (placeholders filled, no-cache, an ETag so revalidation is a 304). All are first-class pages: canonical, OG tags, listed in `_SITEMAP_PAGES` at 0.8 — `/people-search` is "Claude for people search" (the enrichment launch film's destination), `/leads-signals` is "Claude for Monitor Leads Signal" (the buyer-signals launch, built from `/people-search`: the agent runs the check on its own schedule and diffs against its last list; treg itself neither schedules nor diffs), `/grokbot` the "Grok Bot for Outreach" animatic plus the six-bot treg team gallery (ICP Map Coach, Lookalike Scout, Rival Watch Desk, SERP Watch Team, Creator Shortlist Crew, and GTM Expert, each linked directly to its `x.ai/bot/…` page). Its nav, hero and closing CTAs remain the pair **"Setup treg"**, primary — signed in it goes to `/app`, signed out it opens the page's own sign-in modal in place (the `/people-search` pattern; the `href` `/app?ref=grokbot` is only the no-JS fallback) and stashes `treg-ref=grokbot` so the first-run welcome preselects Grok Bot, and **"Install plugin"** → the x.ai plugin page, secondary. `/fable` (file `fable-gtm.html`) is the Claude Fable 5.1 launch: one terminal session that reads the market, plans, spawns four agents and shows one result window at a time. `/ugc` (file `ugc.html`) is the AI UGC workflow article as a page: an arcads-style hero of generated clips, then the five steps told as one pinned Claude Code session on the left that crossfades between steps while the artifacts scroll on the right (trend grid, a five-model character board with real-image showcases, Seedance talking heads, the demo, hook variants and the bill), then pricing against subscription tools and the catalog grid. Its asset paths are **relative** (`media/…`, `logos/…`) so the same file previews from `file://`; that only holds while the routes stay slashless. All are registered in `bootstrap.py`'s route-ownership manifest like every other route. |
|
||||
| `/gtm-engineering` + `/gtm-engineering.md` | The GTM engineering playbook: a diagnostic that turns the problems practitioners raise on Reddit and LinkedIn into symptoms (tick one, get the chapters), then 16 chapters in six parts (define, build the list, timing, reach out, inbound, operate) and four appendices, with a sticky table of contents (a collapsible bar on mobile). Each chapter carries a symptom, the play, a prompt to copy, a visual from a recorded run with its bill, the rule, and a plain line on what treg does and does not cover; chapters marked "Method" have no run behind them. Headings are phrased as the questions answer engines are asked (what a GTM engineer is, the tools they need, the cheapest waterfall, signal-based outbound, people search, Clay alternatives, Claude Code skills), and the FAQPage JSON-LD answers the same questions. It reuses the `/people-search` design (the rotating agent in the H1, whose served HTML names Claude Code; the self-playing demo, captioned as an abbreviated replay with illustrative rows; reveal-on-scroll visuals; the big footer). Hand-written (`gtm-engineering.html`, served through `_static_page`) rather than `_page()`-rendered, because only the hand-written pages load `sitetrack.js`. The Markdown twin (`gtm-engineering.md`, served by `_serve_md` with `X-Robots-Tag: noindex`, named by the page's `rel=alternate` and linked from `llms.txt`) is hand-kept; `tests/test_gtm_engineering_page.py` fails if a chapter heading on the page is missing from it, if a link on the page stops resolving, or if the page loses its canonical, tracking or structured data. Both are hosted-only like `/workflows`: 404 off the reference hosts, and the page joins the sitemap inside the `_hosted()` block. Linked from the homepage footer, the `_page()` footer, the launch-page footers and Related blocks, the five use-case landers, `/resources`, the `/blog` launches, the `/use-cases` and `/workflows` hubs and `llms.txt`. In bundled files those links sit inside `<!--hosted-->…<!--/hosted-->`, which `_strip_hosted` (applied by `_static_page` and the `/llms.txt` route) unwraps on the hosted deployment and removes on a self-hosted one, so no served page points at the 404; the page test checks both sides. Value events: `gtm_diag_tick`, `gtm_chapter_view`, `gtm_copy_*` on a clipboard write that succeeded (`gtm_copy_failed` otherwise), `gtm_faq_open`, `gtm_scroll_proof`, `gtm_cta_*`; any fired before `sitetrack.js` has initialised PostHog are flushed once it has. |
|
||||
| `/jev` | "How to use Jev" (file `jev.html`; the on-page headline reads "How to use Jev for GTM Automation"); the hero carries a literal "What is Jev?" heading. Sections in order: "Quick Jev 101", ONE arrow-driven deck of eleven slides (three on what jev is, five use-case demos judged live by jev with three community recordings credited and linked, three on how to use it in code) staged like the video slides: a kicker, one big header, the visual full width, description text hidden by CSS scoped to `#deck`; then the GTM recipes, whose tab bar is mirrored in the nav everywhere except while the real bar is on screen; then community posts as cards built from each post's own data (avatars and posters bundled in `media/jev/built/`, no X embed script) in a marquee that becomes a swipeable row on touch and reduced motion; then the FAQ with its JSON-LD. The use-case demo script follows the deck through a `deckslide` event, offset by the three opening slides. The recipes are three agent prompts to copy, plus a build-your-own one, each with the demo it produces underneath. Every prompt opens with a "Before you build" block: the steps are a reference implementation, not a spec, so the agent asks about the reader's own workflow, states the plan and the cost of one run, and waits for a go-ahead. Setup is then two steps: treg through `treg.to/llms.txt` (never the install one-liner), and jev as OPTIONAL. With a Vercel AI Gateway key the agent calls jev's evaluation-model endpoint; without one it judges behind the same `state`/`questions` interface itself and labels those results `judge: agent`, so the build works today and switching to jev is a one-line change. `tests/test_jev.py` pins all of it. The X launch radar recipe is **live**: `/jev/xboost.json` serves the document `treg-worker jev xboost` stores daily under Ephemeral (`jev`/`xboost`), else the bundled snapshot `media/jev/xboost-seed.json` flagged `snapshot: true`; `POST /jev/xboost/judge {url}` runs the same forensics + jev on one visitor-pasted post (5 per IP and 60 fleet-wide per hour via ratestore, 503 until `jev_treg_token` and `ai_gateway_api_key` are set) and prepends it to the document's `manual` list, which survives the daily run. treg is a client of itself in that pipeline (`application/jev_xboost.py` calls `/call/` with the demo team's token), so the receipt is a real bill. The signup-triage and signal-first-leads recipes replay bundled runs in `media/jev/*.json` with every email address replaced; `tests/test_jev.py` pins that. Same nav, footer, capture scripts, sitemap priority and `_BLOG_LAUNCHES` entry as the other landings. |
|
||||
| `/catalog` | The dashboard SPA, in public mode — the marketplace's Catalog view on an indexable URL. |
|
||||
| `/catalog/<slug>/<key>` | The same SPA, on one capability's comparison (a capability two or more providers serve on that shelf, `Catalog.compared`; `<key>` drops the platform prefix). Title `{capability}: {n} APIs compared \| treg.to`, a no-JS provider list, breadcrumbs. Every one is in the sitemap (`_comparison_paths`, the same rule behind the shelf's comparison cards), and `tests/test_catalog_api.py` asks each for a 200; a capability only one provider serves is a 404. The route's slug converter never matches the catalog's API segments (`_CATALOG_RESERVED`: `call`, `platforms`, `providers`, …), whatever the route order. |
|
||||
|
||||
@@ -177,6 +177,8 @@ _CONTROL_ROUTE_KEYS: frozenset[RouteKey] = frozenset({
|
||||
('/ugc', ('GET',), 'ugc_page'),
|
||||
('/people-search', ('GET',), 'people_search_page'),
|
||||
('/leads-signals', ('GET',), 'leads_signals_page'),
|
||||
('/gtm-engineering', ('GET',), 'gtm_engineering_page'),
|
||||
('/gtm-engineering.md', ('GET',), 'gtm_engineering_md'),
|
||||
('/jev', ('GET',), 'jev_page'),
|
||||
('/jev/xboost.json', ('GET',), 'jev_xboost_json'),
|
||||
('/jev/xboost/judge', ('POST',), 'jev_xboost_judge'),
|
||||
|
||||
+45
-4
@@ -197,6 +197,7 @@ def _page(title: str, description: str, path: str, body: str, ld: list[dict],
|
||||
# The job, workflow and agent pages exist on the hosted deployment only (`_hosted`): a
|
||||
# self-hosted registry must not put three 404s in its own footer.
|
||||
hub_links = ('<a href="/use-cases">Use cases</a><a href="/workflows">Workflows</a>'
|
||||
'<a href="/gtm-engineering">GTM engineering</a>'
|
||||
'<a href="/agents">Agents</a><a href="/blog">Blog</a>' if _hosted() else "")
|
||||
return HTMLResponse(f"""<!doctype html>
|
||||
<html lang="en">
|
||||
@@ -1664,7 +1665,8 @@ async def use_cases_hub():
|
||||
'</div>' + blocks
|
||||
+ '<section class="cat"><h2>Everything else</h2><div class="cap"><p style="margin:0">These are the jobs '
|
||||
'written up so far. The full menu is on the agent pages, and the whole catalog is at '
|
||||
'<a href="/catalog">/catalog</a>. The multi-step versions are at <a href="/workflows">/workflows</a>.'
|
||||
'<a href="/catalog">/catalog</a>. The multi-step versions are at <a href="/workflows">/workflows</a>, '
|
||||
'and the whole sequence, chapter by chapter, is the <a href="/gtm-engineering">GTM engineering playbook</a>.'
|
||||
'</p></div></section></main>')
|
||||
ld = [{"@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [
|
||||
{"@type": "ListItem", "position": 1, "name": "treg.to", "item": base + "/"},
|
||||
@@ -2003,7 +2005,8 @@ async def workflows_hub(observations: endpoint_stats.EndpointObservationReader =
|
||||
f'</div><section class="cat"><div class="grid">{"".join(cards)}</div></section>'
|
||||
'<section class="cat"><h2>Everything else</h2><div class="cap"><p style="margin:0">The single-job '
|
||||
'versions are at <a href="/use-cases">/use-cases</a>, and the whole catalog is at '
|
||||
'<a href="/catalog">/catalog</a>.</p></div></section></main>')
|
||||
'<a href="/catalog">/catalog</a>. How the workflows fit together is the '
|
||||
'<a href="/gtm-engineering">GTM engineering playbook</a>.</p></div></section></main>')
|
||||
ld = [{"@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [
|
||||
{"@type": "ListItem", "position": 1, "name": "treg.to", "item": base + "/"},
|
||||
{"@type": "ListItem", "position": 2, "name": "Workflows", "item": base + "/workflows"}]}]
|
||||
@@ -3308,7 +3311,7 @@ async def llms_txt(request: Request, db: AsyncSession = Depends(get_session)):
|
||||
from .hub_gate import hub_visible
|
||||
hub_on = (await hub_visible(request, db))[0]
|
||||
base = get_settings().public_url.rstrip("/")
|
||||
return PlainTextResponse(_fill_headline(_strip_routed(f.read_text(encoding="utf-8"), hub_on)).replace("{BASE}", base),
|
||||
return PlainTextResponse(_strip_hosted(_fill_headline(_strip_routed(f.read_text(encoding="utf-8"), hub_on))).replace("{BASE}", base),
|
||||
media_type="text/plain; charset=utf-8")
|
||||
|
||||
|
||||
@@ -3445,6 +3448,8 @@ async def sitemap_xml():
|
||||
add("/workflows", copy_day, "0.8")
|
||||
for w in agent_pages.WORKFLOWS:
|
||||
add(f"/workflows/{w}", copy_day, "0.7")
|
||||
hub = _WEB_DIR / "gtm-engineering.html"
|
||||
add("/gtm-engineering", _iso_day(hub.stat().st_mtime) if hub.exists() else "", "0.8")
|
||||
out.append("</urlset>")
|
||||
return Response("\n".join(out), media_type="application/xml; charset=utf-8",
|
||||
headers={"Cache-Control": "max-age=3600"})
|
||||
@@ -3526,6 +3531,15 @@ def _fill_headline(text: str) -> str:
|
||||
return text.replace("{ENDPOINTS}", endpoints).replace("{PROVIDERS}", str(providers))
|
||||
|
||||
|
||||
def _strip_hosted(text: str) -> str:
|
||||
"""`<!--hosted-->…<!--/hosted-->` marks links to pages that exist only on the hosted deployment
|
||||
(`_hosted`). Hosted, the markers go and the content stays; self-hosted, the whole block goes, so a
|
||||
bundled page or agent-facing file never sends a reader to a 404 on the registry serving it."""
|
||||
if _hosted():
|
||||
return re.sub(r"<!--/?hosted-->\n?", "", text)
|
||||
return re.sub(r"<!--hosted-->.*?<!--/hosted-->\n?", "", text, flags=re.S)
|
||||
|
||||
|
||||
def _serve_md(name: str, hub_on: bool | None = None) -> PlainTextResponse:
|
||||
"""Serve a bundled markdown file as inline text (so "open in new tab" shows it, not a download),
|
||||
with the serving domain templated in. Backs the 'copy markdown' buttons on the docs pages."""
|
||||
@@ -3660,7 +3674,7 @@ def _static_page(name: str, request: Request) -> Response:
|
||||
if not page.exists():
|
||||
raise HTTPException(status_code=404, detail=f"{name} not bundled")
|
||||
base = get_settings().public_url.rstrip("/")
|
||||
html = _fill_headline(page.read_text(encoding="utf-8")).replace("{BASE}", base)
|
||||
html = _strip_hosted(_fill_headline(page.read_text(encoding="utf-8"))).replace("{BASE}", base)
|
||||
etag = '"' + hashlib.sha256(html.encode("utf-8")).hexdigest()[:32] + '"'
|
||||
headers = {"Cache-Control": "no-cache", "ETag": etag}
|
||||
# An edge that compresses the body weakens the tag (W/"..."), so compare the opaque part.
|
||||
@@ -3806,6 +3820,31 @@ async def leads_signals_page(request: Request):
|
||||
return _static_page("leads-signals.html", request)
|
||||
|
||||
|
||||
@app.get("/gtm-engineering", include_in_schema=False)
|
||||
async def gtm_engineering_page(request: Request):
|
||||
"""The GTM-engineering hub: the seven jobs a GTM engineer runs, each linked to its existing
|
||||
page, the workflows as playbooks with their receipts, and the GitHub skills people install
|
||||
next to the catalog job that covers their data step. Hand-written like the launch pages, so it
|
||||
loads sitetrack.js and its reading is measurable; the facts on it are dated in the copy.
|
||||
Hosted only, like the workflows it links to: its runs and credit describe treg.to itself."""
|
||||
if not _hosted():
|
||||
raise HTTPException(status_code=404, detail="not found")
|
||||
return _static_page("gtm-engineering.html", request)
|
||||
|
||||
|
||||
@app.get("/gtm-engineering.md", include_in_schema=False)
|
||||
async def gtm_engineering_md():
|
||||
"""The playbook as Markdown, for agents and answer engines that read text rather than render
|
||||
pages. Hand-kept beside the HTML; `tests/test_gtm_engineering_page.py` fails if a chapter
|
||||
heading on one is missing from the other. `noindex`: the HTML page is the indexed copy and
|
||||
names this one with `rel=alternate`."""
|
||||
if not _hosted():
|
||||
raise HTTPException(status_code=404, detail="not found")
|
||||
resp = _serve_md("gtm-engineering.md")
|
||||
resp.headers["X-Robots-Tag"] = "noindex"
|
||||
return resp
|
||||
|
||||
|
||||
@app.get("/jev", include_in_schema=False)
|
||||
async def jev_page(request: Request):
|
||||
"""Landing page for jev + treg ("jev for GTM engineers"): three agent recipes, each with a prompt
|
||||
@@ -3891,6 +3930,8 @@ async def jev_xboost_judge(request: Request, db: AsyncSession = Depends(get_sess
|
||||
# chronological (newest first), not alphabetical.
|
||||
_BLOG_LAUNCHES: list[tuple[str, str, str, str]] = [
|
||||
# (slug, title, date, one-line blurb)
|
||||
("/gtm-engineering", "The GTM Engineering Playbook", "2026-09-30",
|
||||
"16 chapters from ICP to rollout: a prompt and a rule in each, and the data steps tested on recorded runs."),
|
||||
("/leads-signals", "Claude for Monitor Leads Signal", "2026-09-28",
|
||||
"Your agent checks hiring, funding, job changes and social chatter on a schedule, and reports what's new."),
|
||||
("/jev", "How to use Jev", "2026-09-20",
|
||||
|
||||
@@ -662,7 +662,7 @@
|
||||
</div>
|
||||
<nav class="bf-cols" aria-label="Site">
|
||||
<div class="bf-col"><div class="lab">Explore</div>
|
||||
<a href="/catalog">Catalog</a><a href="/use-cases">Use cases</a><a href="/workflows">Workflows</a><a href="/agents/claude-code">Agents</a></div>
|
||||
<a href="/catalog">Catalog</a><a href="/use-cases">Use cases</a><a href="/workflows">Workflows</a><!--hosted--><a href="/gtm-engineering">GTM engineering</a><!--/hosted--><a href="/agents/claude-code">Agents</a></div>
|
||||
<div class="bf-col"><div class="lab">Build</div>
|
||||
<a href="/tutorial">Docs</a><a href="/docs">API</a><a href="/llms.txt">llms.txt</a><a href="https://github.com/superdesigndev/treg" target="_blank" rel="noopener">GitHub ↗</a></div>
|
||||
<div class="bf-col"><div class="lab">Company</div>
|
||||
|
||||
@@ -1229,7 +1229,7 @@
|
||||
<span class="sf-brand"><svg viewBox="0 0 512 512" aria-hidden="true"><rect width="512" height="512" rx="112" fill="#101010"/><rect x="111" y="111" width="140.5" height="140.5" rx="20" fill="#fff"/><rect x="260.5" y="260.5" width="140.5" height="140.5" rx="20" fill="#fff"/></svg> <b>treg</b><span class="sf-tag">the tool catalog for your agent</span><div class="sf-note">100% open source</div></span>
|
||||
<nav class="sf-cols" aria-label="Site">
|
||||
<div class="sf-col"><div class="lab">Explore</div>
|
||||
<a href="/catalog">Catalog</a><a href="/use-cases">Use cases</a><a href="/workflows">Workflows</a><a href="/agents/claude-code">Agents</a><a href="/people-search">People search</a></div>
|
||||
<a href="/catalog">Catalog</a><a href="/use-cases">Use cases</a><a href="/workflows">Workflows</a><!--hosted--><a href="/gtm-engineering">GTM engineering</a><!--/hosted--><a href="/agents/claude-code">Agents</a><a href="/people-search">People search</a></div>
|
||||
<div class="sf-col"><div class="lab">Build</div>
|
||||
<a href="/tutorial">Docs</a><a href="/docs">API</a><a href="/llms.txt">llms.txt</a><a href="https://github.com/superdesigndev/treg" target="_blank" rel="noopener">GitHub ↗</a></div>
|
||||
<div class="sf-col"><div class="lab">Company</div>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,174 @@
|
||||
# The GTM engineering playbook (2026), with Claude Code and AI agents
|
||||
|
||||
Updated 30 Sep 2026. The page: {BASE}/gtm-engineering
|
||||
|
||||
Sixteen chapters, from defining your ICP to rolling automation out safely. Each starts from a problem GTM
|
||||
engineers post about on Reddit and LinkedIn, then gives the play, a prompt to run in your agent, and the rule
|
||||
to keep, and for every data step, what happened when we ran it. The data steps were run on one ICP: US B2B software, 51-200 staff, selling to
|
||||
sales, marketing, revenue or growth teams or running outbound themselves; the buyer is marketing or growth. Six recorded runs, 502 logged calls,
|
||||
$5.03 metered in total. Process chapters (sending, CRM join, rollout) are method, not runs.
|
||||
|
||||
Set up once, in Claude Code, Codex or Cursor: `set up treg - {BASE}/llms.txt`
|
||||
|
||||
## Where to start (symptoms and chapters)
|
||||
|
||||
- The enrichment bill keeps surprising you: chapters 5 and 2.
|
||||
- Lists come back thin for your market: chapters 7 and 1.
|
||||
- Too many emails bounce, or "valid" means catch-all: chapter 8.
|
||||
- Reps ignore the intent or signal feed: chapters 9 and 10.
|
||||
- Outreach reads like a template: chapter 11.
|
||||
- You reach one person per account, and they are not the buyer: chapter 6.
|
||||
- Nobody can say what the agent may do on its own: chapters 3 and 16.
|
||||
- You cannot say which list, signal or provider produced pipeline: chapters 14 and 15.
|
||||
- Automations stop and you find out days later: chapter 16.
|
||||
|
||||
## What is a GTM engineer, and what tools and data providers do they need in 2026?
|
||||
|
||||
A GTM engineer builds the machine that finds, qualifies and reaches buyers. In 2026 more of it runs from an agent.
|
||||
The stack: an agent (Claude Code, Codex, Cursor, Hermes); a data layer (company and people search, enrichment, email
|
||||
finding and verification, hiring, funding, news, social; treg.to is one, one key, priced per call, your own keys
|
||||
first); skills (the method); a sending tool; a CRM.
|
||||
|
||||
## Write your ICP as fields a provider can filter on
|
||||
|
||||
Split the ICP into filters (country, headcount, category, funding, technology) and checks (judgement per row). Write
|
||||
the buyer as a function, not a title. Keep exclusions explicit.
|
||||
|
||||
Prompt: "Using treg, turn the ICP in icp.md into filters for two company-search providers. Use their free count
|
||||
endpoints only. For each provider show the exact filter object and the count it returns."
|
||||
|
||||
Rule: if a part of the ICP cannot be a filter, it is a check, and it runs before any expensive step.
|
||||
|
||||
## Count the market for free before you pay for a single row
|
||||
|
||||
Recorded 30 Sep 2026, US, 51-200 staff, free counts: CompanyEnrich B2B+SaaS 10,403; the same with funded 2024 or later
|
||||
1,357; the same with funding round series_a 25 (each adds one filter to the first). Dropleads: industry "IT & Services" 15,873; keyword "saas" 5,395; industry
|
||||
"Computer Software" 21. Apollo's Series A filter matched 958 (a paid list page, 23 Sep).
|
||||
|
||||
Rule: no list is bought until two free counts roughly agree and ten sample rows look right.
|
||||
|
||||
## Write down the rules the agent follows, and who can stop it
|
||||
|
||||
At a 50% ICP threshold 27 of 48 companies passed; at 60%, 14 would have. Put thresholds, drops, spend caps and the
|
||||
owner of the stop in a rules file.
|
||||
|
||||
Rule: every threshold is a number in the prompt, every drop has a reason, and one person owns the stop.
|
||||
|
||||
## Lookalikes of your best accounts are candidates, not leads
|
||||
|
||||
Recorded 30 Sep 2026: 71 unique lookalikes from 3 best-fit accounts ($0.006), enriched ($0.20, four providers,
|
||||
cheapest first; the one cheap enrichment comes first because lookalike rows are too thin to judge), same model check
|
||||
at 50%: 8 of 71 passed (11%), and only 5 of those were in the 51-200 band. 13 of 71 were in the band; 53 had 50 staff
|
||||
or fewer.
|
||||
|
||||
Rule: a lookalike goes through the same size filter and ICP check as any other row.
|
||||
|
||||
## Qualify on the fields you already have before any expensive lookup
|
||||
|
||||
Recorded 23 Sep 2026: 50 companies, 48 with a usable domain, 27 passed the ICP check (jev on the team's own key, unmetered), 21 dropped before any
|
||||
paid step, 20 verified deliverable. $2.33 metered, $0.12 per deliverable lead; enriching all 48 would have cost an
|
||||
estimated $4.12. Details: {BASE}/workflows/find-and-verify-a-lead-list
|
||||
|
||||
Rule: no expensive lookup (people, emails, news) runs on a row that has not passed the check; if a row lacks the
|
||||
fields to judge, one cheap enrichment comes first.
|
||||
|
||||
## Which people search APIs work inside an AI agent? Search by role, not "decision makers"
|
||||
|
||||
Recorded 30 Sep 2026 on 8 accounts: a "decision makers" endpoint returned 45 senior people at 5 accounts, mapped by hand: 10 sales,
|
||||
revenue and partnerships; 7 ops and strategy; 6 product, engineering and design; 5 customer success; 5 people and HR;
|
||||
4 finance; 4 founders and assistants; 1 growth; 3 unclear. No title contained "marketing". 3 accounts were
|
||||
rate-limited. Routed people search by title "marketing" returned 20 people at all 8 accounts, $0.00
|
||||
metered (names and titles; contact details are a separate paid step).
|
||||
|
||||
Rule: search for the buyer's function; a "decision makers" list is a map of the company, not your committee.
|
||||
|
||||
## The cheapest way to run waterfall email enrichment from an AI agent
|
||||
|
||||
Bench, 16 Sep 2026, 292 people: cost per correct work email $0.0056 treg.to, $0.0257 Monid, $0.0395 Clay, $0.0427
|
||||
Freckle, $0.0924 Deepline; exact match 90.4%, 79.8%, 89.7%, 90.1%, 86.6%. A routed finder tries providers cheapest
|
||||
first and does not bill misses on per-success providers. Method: {BASE}/blog/work-email-finding-bench
|
||||
|
||||
Rule: pick providers per segment from a test on your own rows, and re-test when the segment changes.
|
||||
|
||||
## Find, then verify, and keep the unknowns apart
|
||||
|
||||
23 Sep run: 27 named people, 21 emails found, 20 deliverable, 1 unknown, 0 invalid; the verifier returned no
|
||||
catch-all flag. A blank catch-all field means unknown, not safe.
|
||||
|
||||
Rule: only a verified-deliverable address goes into the main sequence.
|
||||
|
||||
## How to set up signal-based outbound: use signals you can open and date
|
||||
|
||||
Recorded 30 Sep 2026 on 27 accounts: 16 had open sales, marketing or growth roles posted or first seen in the last 60
|
||||
days; 355 of 675 postings returned were already closed; the funding provider returned no round from the last 12
|
||||
months (latest May 2025). Both checks cost $1.35. Install the signals skill:
|
||||
`npx skills add superdesigndev/treg --skill lead-signals`
|
||||
|
||||
Rule: no source link, no signal. No "why now", no outreach.
|
||||
|
||||
## Score fit and timing together, then work the top tier first
|
||||
|
||||
Tiers on the 27 accounts: A (fit at least 60% and 2+ open GTM roles in 60 days) 8, B (1+) 8, C 11.
|
||||
|
||||
Rule: work tier A this week; tier C gets nothing until a signal moves it.
|
||||
|
||||
## Let the agent research. Let a person write, or at least approve.
|
||||
|
||||
23 Sep run: 19 companies had a news event; scored as a first line on a 0 to 3 scale, 4 of 19 were decent or better
|
||||
(mean 1.79).
|
||||
|
||||
Rule: nothing is sent that a person has not read.
|
||||
|
||||
## Sending infrastructure and replies: what practitioners recommend
|
||||
|
||||
Not treg. Conservative volume, bounces and complaints watched per domain; classify replies, route with context, a
|
||||
person approves, outcome written back to the row.
|
||||
|
||||
## Enrich an inbound lead from its email domain and route it in seconds
|
||||
|
||||
Recorded 30 Sep 2026, 20 domains not looked up before: median 2.2 s (p90 4.5 s), $0.053 total, three providers. Fill:
|
||||
employees 20/20, location 20/20, industry 16/20, description 13/20. Repeat lookups of already-enriched domains: median
|
||||
1.15 s, about a fifth of the price. This measures the lookup, not a full routing flow.
|
||||
`treg call treg.companies.enrich --method POST --data '{"domain":"acme.com"}'`
|
||||
|
||||
Rule: every inbound lead is enriched and routed before a person opens it.
|
||||
|
||||
## Tag every row, so you can tell which list, signal and provider paid off
|
||||
|
||||
Store per row: source list, signal, the provider that found the email, the verifier's verdict. Join to CRM outcomes
|
||||
monthly.
|
||||
|
||||
Rule: a row without its source and provider does not go into a sequence.
|
||||
|
||||
## The metric stack: system health, performance, efficiency
|
||||
|
||||
System health: counts agree, enrichment fill rate, share deliverable. Performance: replies, meetings, opportunities
|
||||
by source, signal and tier. Efficiency: cost per usable result ($0.12 per deliverable lead in our run), share dropped
|
||||
before paying (21 of 48), time to first touch (2.2 s median to enrich a new domain).
|
||||
|
||||
## Roll automation out like software: shadow, small segment, human gate, then autonomy
|
||||
|
||||
What broke in our runs without stopping them: a finder out of capacity, a buying-group endpoint out of capacity, 3
|
||||
accounts rate-limited, and our own parser bug ($1.08 re-run). Alert on expected counts per stage; store raw
|
||||
responses; cap spend per run.
|
||||
|
||||
Rule: nothing goes autonomous until it has run in shadow, and every stage reports its row count.
|
||||
|
||||
## The best Claude Code skills for GTM engineering, and the data step each leaves to you
|
||||
|
||||
coreyhaines31/marketingskills (cold email, competitor profiling), mvanhorn/last30days-skill (topic research),
|
||||
AgriciDaniel/claude-seo (SEO), zubair-trabzada/geo-seo-claude (AI visibility), phuryn/pm-skills (battlecards),
|
||||
swan-gtm/gtm-skills (account research), superdesigndev/treg (buyer signals). Not yet run with treg end to end.
|
||||
|
||||
## Clay alternatives for GTM engineers who work in Claude Code or Codex
|
||||
|
||||
Keep Clay for a shared visual table. Work in the agent with a per-call data layer when you want the playbook in
|
||||
prompts. Cost per correct email on the same 292 people: see the waterfall chapter above.
|
||||
|
||||
## Every recorded run behind this playbook
|
||||
|
||||
30 Sep playbook runs ($2.70, including a $1.08 re-run after our own parsing bug), 23 Sep lead list ($2.33), 16 Sep work-email bench, and the workflows at {BASE}/workflows
|
||||
|
||||
## Glossary and questions
|
||||
|
||||
ICP, TAM, check, waterfall, catch-all, signal, tier, shadow mode: defined on the page.
|
||||
@@ -925,7 +925,7 @@ footer{margin-top:150px;border-top:1px solid var(--line);position:relative;overf
|
||||
</div>
|
||||
<nav class="foot-cols" aria-label="Site">
|
||||
<div class="foot-col"><div class="lab">Explore</div>
|
||||
<a href="/search?ref=landing-footer" onclick="window.TregTracking&&TregTracking.capture('nav_clicked',{target:'tools',from:'landing-footer'})">Tools</a><a href="/catalog">Catalog</a><a href="/enrich-arena">Enrich Arena</a><!--hosted--><a href="/use-cases">Use cases</a><a href="/workflows">Workflows</a><a href="/agents">Agents</a><a href="/blog">Blog</a><!--/hosted--></div>
|
||||
<a href="/search?ref=landing-footer" onclick="window.TregTracking&&TregTracking.capture('nav_clicked',{target:'tools',from:'landing-footer'})">Tools</a><a href="/catalog">Catalog</a><a href="/enrich-arena">Enrich Arena</a><!--hosted--><a href="/use-cases">Use cases</a><a href="/workflows">Workflows</a><a href="/gtm-engineering">GTM playbook</a><a href="/agents">Agents</a><a href="/blog">Blog</a><!--/hosted--></div>
|
||||
<div class="foot-col"><div class="lab">Build</div>
|
||||
<a href="/tutorial">Docs</a><a href="/docs">API</a><a href="/llms.txt">llms.txt</a><a href="https://github.com/superdesigndev/treg" target="_blank" rel="noopener">GitHub ↗</a></div>
|
||||
<div class="foot-col"><div class="lab">Company</div>
|
||||
|
||||
@@ -939,6 +939,10 @@
|
||||
<section class="section" id="related" style="padding-top:60px;padding-bottom:80px">
|
||||
<h2 style="margin-bottom:28px">Related</h2>
|
||||
<div style="max-width:900px;margin:0 auto;display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:14px">
|
||||
<!--hosted--><a href="/gtm-engineering" style="display:block;padding:18px 20px;background:#fff;border-radius:14px;box-shadow:0 1px 2px rgba(20,18,12,.05),0 4px 14px -6px rgba(20,18,12,.08);text-decoration:none;color:inherit;transition:box-shadow .24s">
|
||||
<b style="display:block;font-size:15px;margin-bottom:4px">GTM engineering playbook</b>
|
||||
<span style="font-size:13px;color:var(--muted)">16 chapters from ICP to rollout, the data steps tested on real runs</span>
|
||||
</a><!--/hosted-->
|
||||
<a href="/people-search" style="display:block;padding:18px 20px;background:#fff;border-radius:14px;box-shadow:0 1px 2px rgba(20,18,12,.05),0 4px 14px -6px rgba(20,18,12,.08);text-decoration:none;color:inherit;transition:box-shadow .24s">
|
||||
<b style="display:block;font-size:15px;margin-bottom:4px">People search</b>
|
||||
<span style="font-size:13px;color:var(--muted)">Find the person and verified email behind a signal</span>
|
||||
@@ -966,7 +970,7 @@
|
||||
</div>
|
||||
<nav class="bf-cols" aria-label="Site">
|
||||
<div class="bf-col"><div class="lab">Explore</div>
|
||||
<a href="/catalog">Catalog</a><a href="/use-cases">Use cases</a><a href="/workflows">Workflows</a><a href="/agents/claude-code">Agents</a><a href="/blog">Blog</a></div>
|
||||
<a href="/catalog">Catalog</a><a href="/use-cases">Use cases</a><a href="/workflows">Workflows</a><!--hosted--><a href="/gtm-engineering">GTM engineering</a><!--/hosted--><a href="/agents/claude-code">Agents</a><a href="/blog">Blog</a></div>
|
||||
<div class="bf-col"><div class="lab">Build</div>
|
||||
<a href="/tutorial">Docs</a><a href="/docs">API</a><a href="/llms.txt">llms.txt</a><a href="https://github.com/superdesigndev/treg" target="_blank" rel="noopener">GitHub ↗</a></div>
|
||||
<div class="bf-col"><div class="lab">Company</div>
|
||||
|
||||
@@ -813,6 +813,10 @@ Example (an agent calling Intercom with no key on its box):
|
||||
(`treg scan/upload clis`), shell mode (`treg shell`), and the local-run security sandbox; and
|
||||
[Team access control]({BASE}/tutorial-access.md) - which tools each member may use + the
|
||||
local-run on/off dial.
|
||||
<!--hosted-->
|
||||
- [GTM engineering playbook]({BASE}/gtm-engineering.md): 16 chapters from ICP to rollout, each with a
|
||||
prompt and a rule; the data steps (lists, enrichment, signals, inbound) were tested on recorded runs.
|
||||
<!--/hosted-->
|
||||
- [The official Claude skill]({BASE}/skill.md): the 3-persona (consumer/creator/admin) skill —
|
||||
save it to `~/.claude/skills/treg/SKILL.md` (install.sh does this automatically).
|
||||
- [Web dashboard]({BASE}/): sign in and manage everything in the browser (tools, secrets,
|
||||
|
||||
@@ -842,6 +842,10 @@
|
||||
<section class="section" id="related" style="padding-top:60px;padding-bottom:80px">
|
||||
<h2 style="margin-bottom:28px">Related</h2>
|
||||
<div style="max-width:900px;margin:0 auto;display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:14px">
|
||||
<!--hosted--><a href="/gtm-engineering" style="display:block;padding:18px 20px;background:#fff;border-radius:14px;box-shadow:0 1px 2px rgba(20,18,12,.05),0 4px 14px -6px rgba(20,18,12,.08);text-decoration:none;color:inherit;transition:box-shadow .24s">
|
||||
<b style="display:block;font-size:15px;margin-bottom:4px">GTM engineering playbook</b>
|
||||
<span style="font-size:13px;color:var(--muted)">16 chapters from ICP to rollout, the data steps tested on real runs</span>
|
||||
</a><!--/hosted-->
|
||||
<a href="/use-cases/people-search" style="display:block;padding:18px 20px;background:#fff;border-radius:14px;box-shadow:0 1px 2px rgba(20,18,12,.05),0 4px 14px -6px rgba(20,18,12,.08);text-decoration:none;color:inherit;transition:box-shadow .24s">
|
||||
<b style="display:block;font-size:15px;margin-bottom:4px">Compare providers</b>
|
||||
<span style="font-size:13px;color:var(--muted)">Priced comparison of people search APIs</span>
|
||||
@@ -881,7 +885,7 @@
|
||||
</div>
|
||||
<nav class="bf-cols" aria-label="Site">
|
||||
<div class="bf-col"><div class="lab">Explore</div>
|
||||
<a href="/catalog">Catalog</a><a href="/use-cases">Use cases</a><a href="/workflows">Workflows</a><a href="/agents/claude-code">Agents</a><a href="/blog">Blog</a></div>
|
||||
<a href="/catalog">Catalog</a><a href="/use-cases">Use cases</a><a href="/workflows">Workflows</a><!--hosted--><a href="/gtm-engineering">GTM engineering</a><!--/hosted--><a href="/agents/claude-code">Agents</a><a href="/blog">Blog</a></div>
|
||||
<div class="bf-col"><div class="lab">Build</div>
|
||||
<a href="/tutorial">Docs</a><a href="/docs">API</a><a href="/llms.txt">llms.txt</a><a href="https://github.com/superdesigndev/treg" target="_blank" rel="noopener">GitHub ↗</a></div>
|
||||
<div class="bf-col"><div class="lab">Company</div>
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
<section><div class="wrap">
|
||||
<div class="seclab">Workflows</div>
|
||||
<div class="cards">
|
||||
<!--hosted--><a class="card" href="/gtm-engineering"><h4>The GTM engineering playbook</h4><p>16 chapters from ICP to rollout, with prompts, rules and the data steps tested on recorded runs.</p></a><!--/hosted-->
|
||||
<a class="card" href="/use-cases/seo-data-for-ai-agents"><h4>SEO & search results</h4><p>Live Google results, keyword volume, difficulty and backlinks, priced per call.</p></a>
|
||||
<a class="card" href="/use-cases/lead-enrichment-for-ai-agents"><h4>Lead enrichment</h4><p>Find companies, identify the decision-maker, verify the work email. Misses are free.</p></a>
|
||||
<a class="card" href="/use-cases/social-trend-research-for-ai-agents"><h4>Social & creator trends</h4><p>Posts, creators and comments across TikTok, Reddit, YouTube and X, no platform approval.</p></a>
|
||||
|
||||
@@ -206,7 +206,7 @@ One MCP connection gives your agent access to competitor ad research across Meta
|
||||
and LinkedIn.</p></div></details><details data-ev="lp_objection_open" data-q="What about Google Ads Transparency?"><summary>What about Google Ads Transparency?</summary><div class="body"><p>Google's Ads Transparency Center is in the catalog via DataForSEO and SerpApi. Your agent can
|
||||
search by advertiser domain and get back creatives, spend estimates and targeting.</p>
|
||||
<hr /></div></details></div></section>
|
||||
<section class="related"><div class="wrap"><div class="seclab">Next steps</div><h2>Next steps</h2><ul class="related-list"><li><a href="/use-cases/ads-a-competitor-is-running-now">Ads a Competitor Is Running Now</a></li><li><a href="/use-cases/keywords-a-domain-bids-on">Keywords a Domain Bids On</a></li><li><a href="/use-cases/your-own-campaign-performance">Your Own Campaign Performance</a></li><li><a href="/use-cases/google-results-for-a-keyword">Google Results for a Keyword</a></li></ul></div></section>
|
||||
<section class="related"><div class="wrap"><div class="seclab">Next steps</div><h2>Next steps</h2><ul class="related-list"><!--hosted--><li><a href="/gtm-engineering">The GTM engineering playbook</a></li><!--/hosted--><li><a href="/use-cases/ads-a-competitor-is-running-now">Ads a Competitor Is Running Now</a></li><li><a href="/use-cases/keywords-a-domain-bids-on">Keywords a Domain Bids On</a></li><li><a href="/use-cases/your-own-campaign-performance">Your Own Campaign Performance</a></li><li><a href="/use-cases/google-results-for-a-keyword">Google Results for a Keyword</a></li></ul></div></section>
|
||||
<section class="final"><div class="wrap">
|
||||
<h2>Find out what the category is running, before your next launch</h2>
|
||||
<div class="ctas"><a class="candy" href="/app?ref=p4" data-ev="lp_cta_primary" data-page="p4">Start Free</a></div>
|
||||
|
||||
@@ -210,7 +210,7 @@ models, no.</p></div></details><details data-ev="lp_objection_open" data-q="Whic
|
||||
client that supports the authorization spec can connect with OAuth. Anything that can run a shell command,
|
||||
Codex included, can use the <code>treg</code> CLI or plain HTTP.</p>
|
||||
<hr /></div></details></div></section>
|
||||
<section class="related"><div class="wrap"><div class="seclab">Next steps</div><h2>Next steps</h2><ul class="related-list"><li><a href="/use-cases/build-a-company-list-by-industry-size-or-tech">Build a Company List by Industry, Size or Tech</a></li><li><a href="/use-cases/enrich-a-company">Enrich a Company From Its Domain</a></li><li><a href="/use-cases/employee-reviews-of-a-company">Employee Reviews of a Company</a></li><li><a href="/use-cases/job-postings-across-companies">Job Postings Across Companies</a></li></ul></div></section>
|
||||
<section class="related"><div class="wrap"><div class="seclab">Next steps</div><h2>Next steps</h2><ul class="related-list"><!--hosted--><li><a href="/gtm-engineering">The GTM engineering playbook</a></li><!--/hosted--><li><a href="/use-cases/build-a-company-list-by-industry-size-or-tech">Build a Company List by Industry, Size or Tech</a></li><li><a href="/use-cases/enrich-a-company">Enrich a Company From Its Domain</a></li><li><a href="/use-cases/employee-reviews-of-a-company">Employee Reviews of a Company</a></li><li><a href="/use-cases/job-postings-across-companies">Job Postings Across Companies</a></li></ul></div></section>
|
||||
<section class="final"><div class="wrap">
|
||||
<h2>Research a market this afternoon, without buying a database</h2>
|
||||
<div class="ctas"><a class="candy" href="/app?ref=p5" data-ev="lp_cta_primary" data-page="p5">Start Free</a></div>
|
||||
|
||||
@@ -185,7 +185,7 @@ because it is a workflow tool, not a data API.</p></div></details><details data-
|
||||
through one connection. Install once, and every provider in the catalog answers to it. See <code>/llms.txt</code>
|
||||
for the setup line.</p>
|
||||
<hr /></div></details></div></section>
|
||||
<section class="related"><div class="wrap"><div class="seclab">Next steps</div><h2>Next steps</h2><ul class="related-list"><li><a href="/people-search">Run with your agent</a></li><li><a href="/use-cases/people-search">Compare providers</a></li><li><a href="/workflows/find-and-verify-a-lead-list">Build a Verified Lead List</a></li><li><a href="/use-cases/find-professional-emails">Find Professional Emails</a></li><li><a href="/use-cases/verify-an-email">Verify an Email Before You Send</a></li><li><a href="/use-cases/enrich-a-person">Enrich a Person</a></li><li><a href="/use-cases/find-phone-numbers">Find Phone Numbers</a></li></ul></div></section>
|
||||
<section class="related"><div class="wrap"><div class="seclab">Next steps</div><h2>Next steps</h2><ul class="related-list"><!--hosted--><li><a href="/gtm-engineering">The GTM engineering playbook</a></li><!--/hosted--><li><a href="/people-search">Run with your agent</a></li><li><a href="/use-cases/people-search">Compare providers</a></li><li><a href="/workflows/find-and-verify-a-lead-list">Build a Verified Lead List</a></li><li><a href="/use-cases/find-professional-emails">Find Professional Emails</a></li><li><a href="/use-cases/verify-an-email">Verify an Email Before You Send</a></li><li><a href="/use-cases/enrich-a-person">Enrich a Person</a></li><li><a href="/use-cases/find-phone-numbers">Find Phone Numbers</a></li></ul></div></section>
|
||||
<section class="final"><div class="wrap">
|
||||
<h2>Your next list can be built, enriched and verified in one prompt</h2>
|
||||
<div class="ctas"><a class="candy" href="/app?ref=p2" data-ev="lp_cta_primary" data-page="p2">Start Free</a></div>
|
||||
|
||||
@@ -225,7 +225,7 @@ subscriptions, not the suite you read reports in.</p></div></details><details da
|
||||
client that supports the authorization spec can connect with OAuth. Anything that can run a shell command,
|
||||
Codex included, can use the <code>treg</code> CLI or plain HTTP.</p>
|
||||
<hr /></div></details></div></section>
|
||||
<section class="related"><div class="wrap"><div class="seclab">Next steps</div><h2>Next steps</h2><ul class="related-list"><li><a href="/tools/google-search-console">Google Search Console</a></li><li><a href="/tools/dataforseo">DataForSEO</a></li><li><a href="/tools/serpstat">Serpstat</a></li><li><a href="/tools/moz">Moz</a></li><li><a href="/use-cases/keyword-volume-cpc-and-competition">Keyword Volume, CPC and Competition</a></li><li><a href="/use-cases/google-results-for-a-keyword">Google Results for a Keyword</a></li><li><a href="/use-cases/keywords-a-domain-ranks-for">Keywords a Domain Ranks For</a></li><li><a href="/use-cases/backlink-profile-of-a-domain">Backlink Profile of a Domain</a></li></ul></div></section>
|
||||
<section class="related"><div class="wrap"><div class="seclab">Next steps</div><h2>Next steps</h2><ul class="related-list"><!--hosted--><li><a href="/gtm-engineering">The GTM engineering playbook</a></li><!--/hosted--><li><a href="/tools/google-search-console">Google Search Console</a></li><li><a href="/tools/dataforseo">DataForSEO</a></li><li><a href="/tools/serpstat">Serpstat</a></li><li><a href="/tools/moz">Moz</a></li><li><a href="/use-cases/keyword-volume-cpc-and-competition">Keyword Volume, CPC and Competition</a></li><li><a href="/use-cases/google-results-for-a-keyword">Google Results for a Keyword</a></li><li><a href="/use-cases/keywords-a-domain-ranks-for">Keywords a Domain Ranks For</a></li><li><a href="/use-cases/backlink-profile-of-a-domain">Backlink Profile of a Domain</a></li></ul></div></section>
|
||||
<section class="final"><div class="wrap">
|
||||
<h2>Your next keyword plan can be built by the agent that is already open</h2>
|
||||
<div class="ctas"><a class="candy" href="/app?ref=p1" data-ev="lp_cta_primary" data-page="p1">Start Free</a></div>
|
||||
|
||||
@@ -198,7 +198,7 @@ that answer the same queries at $0.001 per call. Connect via MCP and your agent
|
||||
data back. You are not running a scraper; you are calling an API that has one.</p></div></details><details data-ev="lp_objection_open" data-q="Is there a Grok MCP?"><summary>Is there a Grok MCP?</summary><div class="body"><p>Grok is an AI model, not a data source. If you are using Grok and want it to call social data tools,
|
||||
paste the setup line from <code>/llms.txt</code> into Grok and it can use the treg.to catalog.</p>
|
||||
<hr /></div></details></div></section>
|
||||
<section class="related"><div class="wrap"><div class="seclab">Next steps</div><h2>Next steps</h2><ul class="related-list"><li><a href="/use-cases/find-creators-by-keyword">Find Creators by Keyword</a></li><li><a href="/use-cases/youtube-channel-stats">YouTube Channel Stats</a></li><li><a href="/use-cases/search-posts-by-keyword">Search Posts by Keyword</a></li><li><a href="/use-cases/mine-the-comments">Mine the Comments</a></li></ul></div></section>
|
||||
<section class="related"><div class="wrap"><div class="seclab">Next steps</div><h2>Next steps</h2><ul class="related-list"><!--hosted--><li><a href="/gtm-engineering">The GTM engineering playbook</a></li><!--/hosted--><li><a href="/use-cases/find-creators-by-keyword">Find Creators by Keyword</a></li><li><a href="/use-cases/youtube-channel-stats">YouTube Channel Stats</a></li><li><a href="/use-cases/search-posts-by-keyword">Search Posts by Keyword</a></li><li><a href="/use-cases/mine-the-comments">Mine the Comments</a></li></ul></div></section>
|
||||
<section class="final"><div class="wrap">
|
||||
<h2>Ask what the internet is saying today, and get real posts back</h2>
|
||||
<div class="ctas"><a class="candy" href="/app?ref=p3" data-ev="lp_cta_primary" data-page="p3">Start Free</a></div>
|
||||
|
||||
@@ -999,6 +999,24 @@
|
||||
"name": "leads_signals_page",
|
||||
"path": "/leads-signals"
|
||||
},
|
||||
{
|
||||
"kind": "APIRoute",
|
||||
"methods": [
|
||||
"GET",
|
||||
"HEAD"
|
||||
],
|
||||
"name": "gtm_engineering_page",
|
||||
"path": "/gtm-engineering"
|
||||
},
|
||||
{
|
||||
"kind": "APIRoute",
|
||||
"methods": [
|
||||
"GET",
|
||||
"HEAD"
|
||||
],
|
||||
"name": "gtm_engineering_md",
|
||||
"path": "/gtm-engineering.md"
|
||||
},
|
||||
{
|
||||
"kind": "APIRoute",
|
||||
"methods": [
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
"""The GTM-engineering hub: a hand-written page that links the seven job pages, the workflows and
|
||||
the public skills. It is only useful if every link on it resolves, it can be measured, and it
|
||||
describes treg.to only where treg.to serves it."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
|
||||
from httpx import ASGITransport, AsyncClient
|
||||
|
||||
from treg.api import app
|
||||
from treg.config import get_settings
|
||||
|
||||
PATH = "/gtm-engineering"
|
||||
|
||||
|
||||
async def test_hub_is_served_canonical_and_measurable(clients: AsyncClient):
|
||||
r = await clients.get(PATH)
|
||||
assert r.status_code == 200
|
||||
html = r.text
|
||||
assert '<link rel="canonical" href="' in html and f'{PATH}"/>' in html
|
||||
assert "{BASE}" not in html and "{ENDPOINTS}" not in html and "{PROVIDERS}" not in html
|
||||
# Hand-written pages are the ones PostHog sees; the hub exists partly to be measured.
|
||||
# The agent name in the H1 rotates in the browser; what a crawler reads must already be whole.
|
||||
assert '<span id="agName">Claude Code</span>' in html
|
||||
assert re.search(r"<h1>.*GTM engineering playbook.*Claude Code.*</h1>", html, re.S)
|
||||
title = re.search(r"<title>(.*?)</title>", html).group(1)
|
||||
assert len(title.replace("&", "&")) <= 62, title
|
||||
assert '<script src="/sitetrack.js"></script>' in html
|
||||
assert '<script src="/adtrack.js"></script>' in html
|
||||
kinds = []
|
||||
for block in re.findall(r'<script type="application/ld\+json">(.*?)</script>', html, re.S):
|
||||
kinds.append(json.loads(block)["@type"])
|
||||
assert kinds == ["BreadcrumbList", "Article", "FAQPage"]
|
||||
|
||||
|
||||
async def test_every_internal_link_on_the_hub_resolves(clients: AsyncClient):
|
||||
"""The hub is a page of links; a dead one is the failure nobody notices."""
|
||||
html = (await clients.get(PATH)).text
|
||||
# /app is the signed-in dashboard every Start button points at, not a page of this site.
|
||||
links = sorted({h for h in re.findall(r'href="(/[^"#?]*)', html)
|
||||
if not h.startswith("//") and h != "/app"})
|
||||
assert "/workflows/find-and-verify-a-lead-list" in links and "/people-search" in links
|
||||
for href in links:
|
||||
r = await clients.get(href)
|
||||
assert r.status_code == 200, href
|
||||
|
||||
|
||||
async def test_hub_is_linked_from_its_pillars_and_listed(clients: AsyncClient):
|
||||
for page in ("/", "/resources", "/people-search", "/leads-signals", "/blog", "/use-cases",
|
||||
"/use-cases/lead-enrichment-for-ai-agents", "/workflows"):
|
||||
assert f'href="{PATH}"' in (await clients.get(page)).text, page
|
||||
assert f"{PATH}<" in (await clients.get("/sitemap.xml")).text
|
||||
# Hosted, the bundled pages and llms.txt keep the links with the markers unwrapped.
|
||||
for page in ("/resources", "/people-search", "/leads-signals", "/grokbot", "/fable",
|
||||
"/use-cases/lead-enrichment-for-ai-agents", "/llms.txt"):
|
||||
r = await clients.get(page)
|
||||
assert r.status_code == 200 and "/gtm-engineering" in r.text, page
|
||||
assert "hosted-->" not in r.text, page
|
||||
|
||||
|
||||
async def test_hub_404s_on_a_self_hosted_registry(monkeypatch):
|
||||
monkeypatch.setenv("TREG_PUBLIC_URL", "https://registry.example.internal")
|
||||
get_settings.cache_clear()
|
||||
try:
|
||||
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://registry") as c:
|
||||
assert (await c.get(PATH)).status_code == 404
|
||||
assert (await c.get(PATH + ".md")).status_code == 404
|
||||
assert f"{PATH}<" not in (await c.get("/sitemap.xml")).text
|
||||
# Nothing served on a self-hosted registry may send a reader (or an agent) to the 404.
|
||||
for page in ("/", "/resources", "/people-search", "/leads-signals", "/grokbot", "/fable",
|
||||
"/use-cases/lead-enrichment-for-ai-agents", "/llms.txt"):
|
||||
r = await c.get(page)
|
||||
assert r.status_code == 200, page
|
||||
assert "/gtm-engineering" not in r.text, page
|
||||
assert "hosted-->" not in r.text, page
|
||||
finally:
|
||||
get_settings.cache_clear()
|
||||
|
||||
|
||||
async def test_markdown_twin_carries_every_chapter(clients: AsyncClient):
|
||||
"""The Markdown copy is hand-kept; a chapter added to the page and not to the twin fails here."""
|
||||
import html as _html
|
||||
page = (await clients.get(PATH)).text
|
||||
md = await clients.get(PATH + ".md")
|
||||
assert md.status_code == 200
|
||||
assert md.headers.get("x-robots-tag") == "noindex"
|
||||
assert "{BASE}" not in md.text
|
||||
norm = lambda s: re.sub(r"[“”\"]", '"', _html.unescape(re.sub(r"<[^>]+>", "", s))).strip()
|
||||
headings = [norm(h) for h in re.findall(r'<h3 class="ct">(.*?)</h3>', page, re.S)]
|
||||
assert len(headings) >= 20
|
||||
md_headings = {norm(h) for h in re.findall(r"^## (.+)$", md.text, re.M)}
|
||||
missing = [h for h in headings if h not in md_headings]
|
||||
assert not missing, missing
|
||||
assert f'rel="alternate" type="text/markdown" href="' in page
|
||||
Reference in New Issue
Block a user