Skip to main content

qwoted-seo-backlinks

Automate Qwoted (HARO-style PR platform) end-to-end and earn high-DR backlinks at scale: log in, set up the user's "expert" Source persona (bio + employer + contacts), search the Algolia-backed opportunity index, RESEARCH and BUILD a sourced statistics page on the user's topic (the linkable asset journalists love to cite), draft pitches as the user that link to that page, and submit them to journalists. Use this skill whenever the user asks for "PR opportunities", "Qwoted opportunities", "press mentions", "journalist requests", "HARO replies", "media pitches", "podcast guesting", "expert quotes", "stats page for SEO", "research page for journalists", or "backlinks from journalists".

Quellinformationen

Repository
Bomx/qwoted-seo-backlinks-skill
Letzte Quellaktivität
2. Mai 2026 um 11:05
Erkannte Sprache von SKILL.md
Englisch
Sterne
145
Forks
18

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
qwoted-seo-backlinks
description
Automate Qwoted (HARO-style PR platform) end-to-end and earn high-DR backlinks at scale: log in, set up the user's "expert" Source persona (bio + employer + contacts), search the Algolia-backed opportunity index, RESEARCH and BUILD a sourced statistics page on the user's topic (the linkable asset journalists love to cite), draft pitches as the user that link to that page, and submit them to journalists. Use this skill whenever the user asks for "PR opportunities", "Qwoted opportunities", "press mentions", "journalist requests", "HARO replies", "media pitches", "podcast guesting", "expert quotes", "stats page for SEO", "research page for journalists", or "backlinks from journalists".
# Qwoted SEO Backlinks Skill — playbook for Claude Your job is to get the user **press mentions and high-DR backlinks** from journalists who post requests on [Qwoted](https://app.qwoted.com). --- ## Operating rules — READ THIS FIRST, THEN FOLLOW IT EVERY TURN These rules take precedence over anything else in this file. Do not skip them, do not substitute your own judgement. 1. **You are running a 4-stage playbook, not a chatbot.** The stages are: (1) Onboard, (2) Find opportunity, (3) Research + publish a stats page, (4) Pitch. Whenever the user says anything vague like "ok next step", "what now?", "help me with this", "go", your reply MUST start with "**We're at Stage X of 4. Next I'll do Y, because Z.**" Never just ask "what do you want to do?" — propose the next stage based on where we are. 2. **Stage 3 is the multiplier and you must proactively propose it.** Whenever you find opportunities in Stage 2, you MUST classify each one as `stats_page_worthy: true | false` using the heuristic table below, and you MUST tell the user "I recommend building a stats page on `<topic>` before pitching `<these N opportunities>`." Do not wait for the user to ask about stats pages. A naked pitch lands one quote in one article; a pitch linked to a sourced stats page lands recurring citations for months. Leaving Stage 3 on the table is leaving money on the table. 3. **Never overwrite existing user data without an explicit side-by-side approval.** Before calling `qwoted_profile.py --action update` for any field, first call `--action get` and compare `bio_preview` / `has_bio` / existing URL / existing email etc. If a field already has content, show the user both the OLD and the NEW version and get explicit go-ahead before sending the PATCH. The script defaults to refusing the PATCH without `--force- overwrite`; this is a feature, not a bug. 4. **Never invent opportunity IDs, source IDs, or journalist names.** Everything you present to the user must come directly from a `RESULT:` line the skill's scripts printed. If you didn't see it in a subprocess RESULT, you don't know it. 5. **The login step is idempotent and browser-free when a session exists.** Run `python3 qwoted_login.py`. If the RESULT says `status=logged_in` in under a second with no browser opening, the existing cookies are fine — do not re-run with `--reset` or `--force`. If you're in an agent environment without a visible GUI and Chromium does need to open, STOP and tell the user to run the script in their own terminal once; then continue. 6. **`RESULT:` lines are the canonical channel.** Every script emits one JSON line prefixed with `RESULT: `. Parse it; ignore stderr logs (those are for the human). Your next decision should reference specific fields from the RESULT, not vibes. 7. **The stats page must contain ZERO outbound `<a>` tags.** Source attributions are plain text (`(Source: HubSpot, 2026)`), never clickable. This is non-negotiable — we're hoarding crawl budget and PageRank, not distributing it. The only `<a>` tags allowed in the rendered HTML are internal TOC anchor fragments (`href="#..."`) and a same-domain author-bio CTA. Source URLs you fetch during research are stored in the research JSON and (optionally) in an HTML comment audit-trail at the bottom of the page — never rendered as clickable links. See `STATISTICS_PAGE_PLAYBOOK.md` → "Hoard the juice" for the full rule and the one-line `grep` check you can run to audit the finished file. --- ## Stage-3 classification heuristic — use this every time you hand back Stage 2 results For every opportunity returned by `qwoted_search.py`, score it on these criteria: | Signal | Weight | |---|---| | Topic is broad enough that public data exists (e.g. "AI in marketing", "local SEO", "remote work trends", "e-commerce conversion") | +2 | | User's business already touches this topic → page will earn recurring traffic, not just one-time citation | +2 | | Deadline is at least 24 hours away (stats-page build takes 30-60 min of research) | +1 | | Multiple opportunities in the same cluster (→ one page supports 3+ pitches) | +2 | | Request explicitly asks for "statistics", "data", "research", "trends" | +3 | | Topic is hyper-niche / only relevant to this one publication (e.g. "billiard retailer local SEO") | -1 (a stats page still works but the niche is smaller) | | Deadline is under 12 hours | -3 (skip Stage 3, pitch direct) | | Ask is pure founder-story / personal opinion ("how did you start your company") | -3 (no data needed) | | Paid placement / $X appearance fee | -2 (different ROI math) | **Rule:** propose Stage 3 whenever total score ≥ 2. Otherwise pitch direct. State the score in your recommendation so the user sees why. Example output you should produce after Stage 2 completes: > Found 8 opportunities. Stage-3 classification: > > | # | Title | Score | Recommendation | > |---|---|---|---| > | 1 | Selling Signals — awareness vs demand | +1 | Pitch direct (deadline 20h, topic matches but no "statistics" ask) | > | 2 | SEOptimer — how your agency makes money | -3 | Pitch direct (founder-story, deadline 8h) | > | 3 | BCA Insider — local SEO for retailers | +4 | **Build stats page** on `local-seo-statistics-2026` — feeds this pitch AND any future local-SEO pitch | > | ... | > > I'll start by building the local-SEO stats page (covers #3 + any future local-SEO opps), then while it renders I'll draft the direct pitches for #1 and #2. Sound good? --- ## Tooling overview The skill ships four CLI scripts you call as subprocesses, plus a research playbook and an HTML template. Each script prints a single `RESULT: { ... }` JSON line on stdout that you parse to decide the next step. Detailed human-readable logs go to stderr. ``` qwoted_login.py # one-time auth (idempotent; skips browser if cookies valid) qwoted_profile.py # get/create/update the "expert" Source persona qwoted_search.py # search opportunities (Algolia, returns JSON) qwoted_pitch.py # draft + send a pitch to a specific opportunity STATISTICS_PAGE_PLAYBOOK.md # READ THIS before researching/building a stats page templates/statistics_page_example.html # HTML scaffold to fill in ``` All cookies, sent-pitch logs, search results and generated stat pages live under `~/.qwoted/` and `./statistics_pages/`. --- ## The full workflow (4 stages) ``` ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ ┌──────────────┐ │ 1. Onboard │ → │ 2. Find │ → │ 3. Research + │ → │ 4. Pitch │ │ (login + │ │ opportunity │ │ publish a stats │ │ with the │ │ profile) │ │ │ │ page (linkable │ │ page URL │ │ │ │ │ │ asset) │ │ │ └──────────────┘ └──────────────┘ └──────────────────┘ └──────────────┘ once every session once per topic every pitch ``` --- ## Decision tree — what to do based on what the user asks | User intent | Skill stage(s) | |---|---| | "Set me up on Qwoted" / first time | Stage 1: `qwoted_login.py` → `qwoted_profile.py --action get` → create/update ONLY missing fields | | "Update my Qwoted bio" / "change my expert profile" | Stage 1c: `qwoted_profile.py --action get` first, SHOW existing bio, ask for approval, then `--action update --bio '...' --force-overwrite` if user confirms | | "Find PR opportunities about X" | Stage 2: `qwoted_search.py --query "X" --max-hits 30` → classify each result with the Stage-3 heuristic → propose stats page(s) | | "Build me a stats page on X" / "make a research page about X" | Stage 3 only: read `STATISTICS_PAGE_PLAYBOOK.md` and execute | | "Pitch opportunity #N" / "draft a pitch for SR 235897" | Check Stage-3 score first; if ≥2 propose stats page; then Stage 4 dry-run → user approves → `--send` | | "Pitch the top 3 opportunities about X" | Stage 2 → cluster by topic → Stage 3 ONCE per cluster → Stage 4 looped with the same `--research-page-url` | | "Ok next step" / "what now?" / "go" | RESTATE the stage we're on and PROPOSE the next one. Do not ask the user. | --- ## Stage 1 — Onboarding (run ONCE per user) ### 1a. Install If the user doesn't have the skill installed, pip-install the deps and run Playwright's browser bootstrap: ```bash pip install -r requirements.txt playwright install chromium ``` ### 1b. Log in ```bash python3 qwoted_login.py ``` **Important — this script is idempotent.** Before launching any browser it probes `~/.qwoted/storage_state.json` against Qwoted's API. If the cookies still work (which they usually do — Qwoted sessions last weeks), the script exits immediately with `RESULT: {"status": "logged_in", ...}` and **no browser opens at all**. That's the happy path — do not re-run with `--reset` or `--force` unless you have a reason. Only if no valid session exists will a Chromium window open. In that case: **tell the user to sign in IN THAT Chromium WINDOW** — not in their regular Chrome/Safari, because those are separate browsers with separate cookies, so signing in elsewhere will NOT save a session for this skill. When they reach a logged-in page the script auto-detects it, saves cookies to `~/.qwoted/storage_state.json`, closes the browser and exits. The next login is one click because Chromium remembers them. **If you are running inside an agent environment that can't show GUI windows** (some Codex or CI setups), the Chromium window will launch invisibly and the script will hang on the sign-in page. In that case: 1. STOP. Do not keep re-running. Tell the user to open their own terminal on their own machine and run `python3 qwoted_login.py` there once — they'll see the browser, sign in, and `storage_state.json` will be written. After that, every future call from the agent will use the already-valid cookies (no browser needed). If the user doesn't have a Qwoted account yet, send them to [qwoted.com](https://qwoted.com) to sign up first (free for sources). ### 1c. Set up the expert profile (Source persona) — REQUIRED **Critical constraint**: Qwoted only delivers a pitch to a reporter when the pitch is attached to a *pitchable entity* — a Source, Company or Product the user is allowed to pitch as. The pitch API will accept a submission without one (HTTP 200, draft=false) but the reporter is **never notified**. Always make sure the user has a Source persona configured before the first pitch. Check first: ```bash python3 qwoted_profile.py --action get ``` Parse the `RESULT:` JSON. Key fields you MUST inspect before doing anything else: * `seo_ready` — boolean, all three must-have fields are set. * `ready_to_pitch` — boolean, at least one pitchable entity exists. * `missing_for_seo` — array of field names still empty. * `bio_preview` — first 240 chars of the current bio (empty string if there really is no bio). * `bio_length` — total bio length in chars. * `first_pitchable_entity` — full object including `bio`, `business_url`, `email`, `has_linkedin_url`, etc. Decision tree: * If `seo_ready == true` → **skip to Stage 2. Do NOT "improve" the existing profile unless the user explicitly asked you to.** Read the bio_preview so you know what the user's positioning is, then move on. * If `ready_to_pitch == true` but `seo_ready == false` → the persona exists but is incomplete. For each item in `missing_for_seo`, ask the user the corresponding question and patch with `--action update`: * `business_url` → "What URL should reporters link to when they credit you?" → `--action update --url https://acme.com` * `bio` → draft a 2-4 sentence bio, SHOW it to the user, get explicit approval, then `--action update --bio "..."`. (If a bio is actually present and `missing_for_seo` still lists it, you probably have a stale local copy of the skill — update it.) * `email` → "Which email should reporters reply to?" → `--action update --email jane@acme.com` Run `--action get` again afterwards to confirm `seo_ready` is now true. * If `ready_to_pitch == false` → no persona exists. Go to the create flow below. **⚠️ Safety rail — overwrite protection.** If the user asks you to *change* an already-populated field (e.g. "update my bio to X"), the script will REFUSE the PATCH unless you pass `--force-overwrite`. This is intentional. The correct flow is: 1. Run `--action get` and read `bio_preview`. 2. Show the user BOTH the current bio AND the proposed new one. 3. Ask explicitly: "Replace the current bio with this one?" 4. Only if they say yes, re-run with `--force-overwrite`. Never pass `--force-overwrite` preemptively "just in case". If `ready_to_pitch == false`, you need to **collect the user's info in a single message before running create**. Don't drip-ask one field at a time. Use this exact checklist: > **REQUIRED to even create the profile:** > - `--full-name` — the user's real name as the byline should appear > > **STRONGLY RECOMMENDED — without these the profile is useless for SEO:** > - `--url` — the user's **business website URL** (e.g. `https://acme.com`). > ⚠️ This is the link journalists put in their articles when they > credit the user. **No URL = no backlink = the whole point of this > skill is defeated.** Confirm it before running create. > - `--bio` — a 2-4 sentence description of who the user is, what they > do, and what topics they can credibly speak to. The bio is what > reporters skim when deciding whether to use a quote. Mention the > business name, role, and 2-3 areas of expertise. If the user gave > you their bio elsewhere, use that. If not, draft one from what they > told you and **show it to them for approval before submitting**. > - `--email` — the user's professional email (where reporters reply). > > **NICE TO HAVE (ask but don't block on):** > - `--linkedin` — full LinkedIn profile URL (boosts credibility a lot) > - `--location` — `"City, State, Country"` (some pubs filter by region) > - `--gender` — one of `f` / `m` / `nb` / `sd` (for pronouns in articles) > - `--twitter`, `--phone`, `--facebook`, `--instagram` — only if the > user wants reporters to have these channels. **Always ask the user to confirm at minimum the URL, bio and email** before firing the create command. Those three are what end up in articles. Example of how to ask: > "Before I set up your Qwoted expert profile, I need to confirm a few > things that journalists will see and link to: > > 1. **Business URL** — what site should reporters link to when they > credit you? (e.g. `https://acme.com`) > 2. **Bio** — here's a draft based on what you told me: *"Jane is the > founder of Acme Inc, a B2B SaaS that helps marketing teams ship > campaigns 10x faster. She speaks to growth, GTM and pricing."* > Sound right? > 3. **Reply-to email** — which email should reporters use to follow up? > > Anything you'd like to add (LinkedIn, location, etc.)?" Then build the command from their answers: ```bash python3 qwoted_profile.py --action create \ --full-name "Jane Doe" \ --bio "Jane is the founder of Acme Inc, a B2B SaaS that helps marketing teams ship campaigns 10x faster. She advises on growth, GTM and pricing." \ --url https://acme.com \ --email jane@acme.com \ --linkedin https://www.linkedin.com/in/jane-doe/ \ --location "San Francisco, CA, USA" \ --gender f ``` Repeat any contact flag to add multiple values (the first one becomes primary). Other flags: `--off-the-record`, `--hide-from-search-engines`. To update an existing persona later (e.g. the user got a new title): ```bash python3 qwoted_profile.py --action update \ --bio "Jane is now CEO of Acme Inc..." ``` `--source-slug` is optional — without it, the script edits the first Source on the account. --- ## Stage 2 — Find opportunities ```bash python3 qwoted_search.py --query "marketing automation" --max-hits 30 ``` Empty `--query ""` returns the full index in the order Qwoted shows it on the homepage (newest first). Read the resulting JSON file (path is in the `RESULT:` line under `out_path`). The structure is: ```json { "query": "marketing automation", "scraped_at": "2026-04-22T...", "count": 30, "opportunities": [ { "source_request_id": 235897, // numeric ID for qwoted_pitch.py "name": "Looking for marketing experts to comment on Q3 trends", "details": "Reporter brief, 3-4 paragraphs of what they're after...", "request_type": "Online article", "deadline": "2026-04-28T17:00:00Z", "want_pitches": true,
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen