agentsclimarketplace

Hector keyword harvesting

Skill hectorai-live/hector-amazon-ads/skills/hector-keyword-harvesting

Hector's Amazon Ads methodology as Claude skills — brand ads audit, keyword harvesting, SQP analysis, and search-term negation, running on the Hector Amazon MCP connector.

Install
npx -y skills add hectorai-live/hector-amazon-ads --skill hector-keyword-harvesting

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • 11 days oldThe repository was created 11 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Use this skill ANY TIME the user asks about keyword harvesting, finding keywords to add, identifying search terms not in exact match, or gap analysis — e.g. "harvest keywords", "what keywords should I add?", "which search terms should I be targeting in exact match?", "find terms with orders not in my exact targeting", "run a harvest for [brand/account]", "show me harvesting opportunities", "keyword gap analysis", or close paraphrases. Also fires when the user wants to add the harvested terms to existing or new campaigns (action phase). Does NOT fire for: "show me my top search terms" (performance report only), "which search terms are wasting spend" (negative keyword task), "what keywords should I pause/remove" (bid or status task), general search-term analytics with no intent to promote terms, placement analysis, or budget questions.

SKILL.md

18.5 KB, ~4.5k tokens by cl100k_base, as published. Nobody here has run it

Hector Keyword Harvesting (v2)

⚠️ CRITICAL OBLIGATIONS — READ BEFORE EVERY USE

  1. Resolve profile_id BEFORE any tool call. Never guess or invent a profile ID. If not in context, resolve via find_profile_by_name or get_amazon_profiles first. This is a hard blocker — no tool call proceeds without a confirmed profile_id.
  2. Run date-resolution skill before setting any date. Always run hector-mcp-date-resolution before setting start_date / end_date. Never trust the session clock.
  3. Pull the account snapshot FIRST to derive min_roas dynamically. Use analytics_seller_vendor_master_overview for the same date window as the harvest to get average account ROAS. min_roas = account_average_ROAS × 0.60. Never hardcode a ROAS threshold.
  4. Default date window is last_30_days. If fewer than 5 harvest candidates are returned, automatically re-run with last_60_days. Inform the user when this escalation happens. Never ask the user for a date range unless they volunteer one.
  5. Always pull 250 rows (limit: 250). Never use the default 5-row preview for harvest calls. The full list must be shown before any action is taken.
  6. Always group results by product/category. Claude reads the search terms semantically and defines the categories — do not rely on any pre-built Hector table. Never present a flat undifferentiated list.
  7. Hard threshold: min_orders = 2. A search term with fewer than 2 orders never appears in the harvest list, regardless of ROAS. No flagging, no grey zone — excluded entirely.
  8. NEVER add keywords without explicit two-phase preview → confirm flow. Call bulk_add_keywords with preview_only: true first. Show the table. Wait for explicit user confirmation before executing.
  9. Never use CPC from analytics as a bid. Always source bids from get_suggested_bids.
  10. Run the closing self-check before every response.

Why this skill exists

On Amazon Ads, search terms are the actual customer queries that triggered an ad. Targeting is what you explicitly told Amazon to match against — an exact keyword, a phrase, an auto campaign, etc. A search term can generate orders while being matched only through broad, phrase, auto, or competitor campaigns — meaning it is never directly controlled or efficiently bid on.

Harvesting is the process of identifying those high-performing search terms and promoting them into exact-match keywords, giving the account direct, controllable, biddable coverage over its best traffic. This is the single highest-ROI routine optimisation on Amazon Ads.


When this skill activates

Fires on:

  • "Harvest keywords / search terms for [brand/account/ASIN]"
  • "What keywords should I add?"
  • "Which search terms should I be targeting in exact match?"
  • "Find me terms with orders that aren't in my exact targeting"
  • "Run a harvest", "show me harvesting opportunities", "keyword gap analysis"
  • "Add the harvested terms to [campaign / ad group]" (triggers action phase)
  • Any request to identify and promote unconverted search terms into exact match

Does NOT fire on:

  • "Show me my top search terms" — performance report, not a harvest (use analytics_search_term_list directly, no grouping or gap logic)
  • "Which search terms are wasting spend?" — negative keyword task, not a harvest
  • "What keywords should I pause / remove?" — bid or status task
  • Pure search-term analytics with no intent to promote terms
  • Placement, budget, or bid-only analysis

Blocking Preconditions

You CANNOT call any Hector MCP analytics tool until ALL THREE of the following are true:

Precondition A — Profile resolved. profile_id must be confirmed. If missing, call find_profile_by_name or get_amazon_profiles and confirm with the user before proceeding.

Precondition B — Date resolved. Run hector-mcp-date-resolution to get verified_today. Default harvest window: last_30_days. Auto-escalate to last_60_days if < 5 candidates found.

Precondition C — Account ROAS fetched. Pull the account snapshot first (same date window) to derive min_roas = account_average_ROAS × 0.60. This must happen before the harvest call.

These are preconditions, not optional setup. Skipping any one produces wrong results.


Step-by-Step Execution

Step 1 — Identify scope

Without asking the user (unless genuinely ambiguous):

  • Account-wide harvest? → No ASIN filter. Proceed.
  • Product/ASIN-scoped harvest? → Note the ASINs or category. Resolve to ASINs via sku_lookup if the user named a product without ASINs.
  • Category groupings: Do not ask the user. Claude will define groupings semantically in Step 4 from the search term text and product names returned.

Default scope when not specified: account-wide.

Step 2 — Resolve profile and date (BLOCKING)

2a. If profile_id is not in context: call find_profile_by_name with the brand/account name. Confirm the resolved profile_id in one line before proceeding.

2b. Run hector-mcp-date-resolution to get verified_today. Set: start_date: last_30_days, end_date: yesterday.

Step 3 — Fetch account snapshot to derive min_roas (BLOCKING)

Call analytics_seller_vendor_master_overview:

profile_id: <resolved>
start_date: last_30_days
end_date: yesterday

From the response, extract average account ROAS. Compute: min_roas = account_average_ROAS × 0.60

Example: account average ROAS = 8.5 → min_roas = 5.1

State this to the user in one line:

"Account average ROAS (last 30 days): 8.5 → using min_roas of 5.1 (60% floor)"

Step 4 — Pull harvest candidates

Primary tool — keyword_harvesting (use for all standard account-wide requests):

profile_id: <resolved>
start_date: last_30_days
end_date: yesterday
min_orders: 2
min_roas: <derived in Step 3>
metrics: [Orders, ROAS, Revenue, Spend]
limit: 250

If fewer than 5 candidates returned → auto-escalate to last_60_days: Re-run the snapshot (Step 3) and the harvest call with start_date: last_60_days. Inform the user:

"Only [N] candidates found in 30 days — expanding to 60 days automatically."

Alternate tool — analytics_search_term_list with harvesting filter: Use ONLY when:

  • User scoped to a specific ASIN (advertised_asin param — not available in keyword_harvesting)
  • User wants additional metric filters keyword_harvesting cannot express
profile_id: <resolved>
start_date: last_30_days        ← or last_60_days if escalated
end_date: yesterday
harvesting: { status: "gap", match_types: ["EXACT"] }
metrics: [Orders, ROAS, Revenue, Spend, Clicks]
metric_filters: [{ field: "Orders", operator: "greater_than", value: 2 }]
grouping_level: "ungrouped"     ← harvesting forces this; never override
advertised_asin: "<ASIN>"       ← only when ASIN-scoped
sort_column: Orders
sort_type: DESC
limit: 250

Threshold rule (hard): Any search term with fewer than 2 orders is excluded entirely. No flagging. No partial display. Not shown.

Step 5 — Group results by product/category (MANDATORY)

Claude reads the search terms semantically and defines categories. Do not ask the user. Do not rely on any Hector categorization table.

How to group:

  • Read the SearchTerm text and ProductName / ASIN columns from the results
  • Identify product signals in the term (e.g. "men's sunscreen spf50" → Sunscreen › Men's)
  • Group like products together (e.g. sunscreen for men + sunscreen for women = Sunscreen)
  • Terms that don't fit a clear product category → group under "General / Mixed"

Present results in this format for each group:

## 📦 [Category Name] — [N] harvest candidates

| Search Term              | Orders | ROAS | Revenue  | Spend   |
|--------------------------|--------|------|----------|---------|
| men's sunscreen spf 50   |  42    | 6.2  | ₹18,400  | ₹2,960  |
| sunscreen for men        |  31    | 5.8  | ₹14,260  | ₹2,459  |
...

After all groups, show a summary table:

| Category         | Harvest Candidates | Already in Exact | Action          |
|------------------|--------------------|------------------|-----------------|
| Sunscreen        | 18                 | 4                | Add 18 to exact |
| Hair Oil         | 12                 | 9                | Add 12 to exact |
| Face Wash        | 7                  | 11               | Add 7 to exact  |
| General / Mixed  | 4                  | 2                | Review manually |

Step 6 — Prompt for action

Immediately after showing the grouped results and summary, ask:

"Which of these keywords do you want to add to a campaign?"

Wait for the user's response. They may:

  • Select specific terms or entire category groups
  • Say "all of them"
  • Say "skip for now"

Step 7 — Existing or new campaign?

Once the user has identified which keywords to add, ask:

"Do you want to add these to existing campaigns or create new campaigns?"

If existing campaigns:

  • The user will map category groups to campaigns (e.g. "Sunscreen keywords → SP-Sunscreen-Exact")
  • Resolve campaign_id via get_campaign_id or search_records
  • Fetch suggested bids via get_suggested_bids for each term
  • Call bulk_add_keywords with preview_only: true → show preview table
  • Wait for explicit confirmation ("confirm", "yes proceed", "looks good")
  • Call bulk_add_keywords with preview_only: false
  • Report outcome. Note: "New keywords appear in analytics within 24–48 hours."

If new campaigns:

  • Ask: "Which ASINs should be advertised in this campaign, and what is the daily budget?"
  • There may be multiple ASINs/ad groups — collect the full list before proceeding
  • Use sp_campaign_preview to show the proposed campaign structure
  • Wait for explicit confirmation
  • Use sp_campaign_execute to launch
  • Report outcome

What NOT to Do

  • Never call any tool before profile_id, date, and account ROAS are all resolved. All three are blocking preconditions.
  • Never hardcode min_roas. It must always be derived as account_average_ROAS × 0.60 from the snapshot in the same date window.
  • Never show fewer than 200 rows when candidates exist. limit must be set to 250.
  • Never present results as a flat unsorted list. Always group by Claude-defined product/category first.
  • Never show a search term with fewer than 2 orders. Hard exclusion — no exceptions.
  • Never use CPC from analytics as a bid. Use get_suggested_bids only.
  • Never execute keyword adds without preview → explicit confirm flow.
  • Never hand-build a master_search_filters KeywordHarvesting block. Use the flat harvesting param in analytics_search_term_list.
  • Never set grouping_level: "grouped" when using the harvesting filter. The endpoint forces ungrouped — do not override.
  • Never ask the user for a date range unless they volunteer one. Default to last_30_days and auto-escalate if needed.
  • Never confuse "top search terms" with harvesting. Showing performance data is not harvesting. The skill does not fire on performance-only requests.

Edge Cases

SituationBehaviour
Fewer than 5 harvest candidates on last_30_daysAuto re-run snapshot + harvest with last_60_days. Inform user. Do not ask.
Still fewer than 5 candidates on last_60_daysReport the count, suggest the user review min_orders (currently 2) or check if account has enough volume. Do not auto-escalate further.
Account snapshot returns no ROAS (new account / no spend)Flag: "Cannot compute dynamic ROAS floor — account has no ROAS data in this window." Ask user to provide a manual min_roas before proceeding.
User scopes to a specific ASINSwitch to analytics_search_term_list with advertised_asin + harvesting filter. keyword_harvesting is account-wide only.
All candidates are already in exact matchReport as a positive finding: "Exact-match coverage is strong for this window." Show already_targeted count as validation.
User says "add all" to existing campaignsGroup by category, confirm one campaign per category group with the user before calling bulk_add_keywords. Never map all terms to one campaign blindly.
User says "new campaign" but gives only one ASINAsk for the full list of ASINs to advertise and the daily budget before calling sp_campaign_preview.
Search terms don't clearly map to any productGroup under "General / Mixed" and flag for manual review. Do not force an incorrect category.
get_suggested_bids returns zero or very high bidFlag the anomaly to the user. Do not silently cap or floor it. Let the user decide the bid.
User volunteers a date range (e.g. "last 90 days")Use their range. Skip the 30-day default and the auto-escalation logic. Still run snapshot in the same window to derive min_roas.

Worked Examples

Example 1 — Standard account-wide harvest, existing campaigns

User: "Run a keyword harvest for <brand> India."

  1. profile_id not in context → call find_profile_by_name("<brand> India") → confirmed.
  2. Run date-resolution skill → verified_today confirmed.
  3. Call analytics_seller_vendor_master_overview (last_30_days) → account average ROAS = 9.0 → min_roas = 5.4. State to user.
  4. Call keyword_harvesting (last_30_days, min_orders: 2, min_roas: 5.4, limit: 250).
  5. 47 candidates returned (> 5 threshold — no escalation needed).
  6. Group semantically: Onion Hair Oil (18), Face Wash (12), Sunscreen (10), Body Lotion (7).
  7. Present grouped tables + summary table.
  8. Ask: "Which of these keywords do you want to add to a campaign?"
  9. User: "All sunscreen ones."
  10. Ask: "Existing or new campaign?"
  11. User: "Existing — SP-Sunscreen-Exact."
  12. Resolve campaign_id. Fetch suggested bids. Call bulk_add_keywords (preview_only: true).
  13. Show preview table. Wait for confirm.
  14. User: "Confirm." → Call bulk_add_keywords (preview_only: false). Report outcome.

Example 2 — Fewer than 5 candidates, auto-escalation

User: "Harvest keywords for our new moisturiser brand."

  1. profile_id resolved. Date resolved.
  2. Snapshot (last_30_days) → account average ROAS = 6.0 → min_roas = 3.6.
  3. keyword_harvesting (last_30_days) → 3 candidates returned.
  4. Auto-escalate: re-run snapshot (last_60_days) → ROAS = 6.2 → min_roas = 3.72.
  5. Re-run keyword_harvesting (last_60_days) → 14 candidates returned.
  6. Inform user: "Only 3 candidates found in 30 days — expanded to 60 days, found 14."
  7. Group: Moisturiser (11), General / Mixed (3). Present tables.
  8. Ask: "Which of these keywords do you want to add to a campaign?"

Example 3 — New campaign path

User (after seeing harvest): "Add the hair oil keywords to a new campaign."

  1. Ask: "Which ASINs should be advertised in this campaign, and what is the daily budget? List all ASINs if there are multiple ad groups."
  2. User provides ASINs + budget.
  3. Call sp_campaign_preview → show proposed campaign structure.
  4. Wait for user confirmation.
  5. Call sp_campaign_execute. Report outcome.

Example 4 — ASIN-scoped harvest

User: "Harvest for our men's sunscreen ASIN B0ABC12345 only."

  1. profile_id and date resolved. Snapshot → min_roas derived.
  2. Use analytics_search_term_list (ASIN filter not in keyword_harvesting):
    advertised_asin: "B0ABC12345"
    harvesting: { status: "gap", match_types: ["EXACT"] }
    metric_filters: [{ field: "Orders", operator: "greater_than", value: 2 }]
    limit: 250
    sort_column: Orders, sort_type: DESC
    
  3. All results under one ASIN → single group "Sunscreen › Men's."
  4. Present table and proceed to Step 6.

Closing Self-Check (RUN BEFORE EVERY RESPONSE)

  • Profile resolved? Is profile_id confirmed before any MCP tool was called?
  • Date resolved? Was hector-mcp-date-resolution run and the window set correctly?
  • Snapshot pulled? Was analytics_seller_vendor_master_overview called first to derive min_roas = account_average_ROAS × 0.60?
  • min_orders = 2 enforced? No term with fewer than 2 orders appears anywhere in output.
  • min_roas is dynamic, not hardcoded? It was derived from the account snapshot.
  • limit set to 250? Not using the default 5-row preview for the harvest call.
  • Auto-escalation logic applied? If < 5 candidates on 30 days, did I re-run on 60 days?
  • Results grouped by Claude-defined product/category? No flat list presented.
  • Summary table shown after all category groups?
  • Action prompt given immediately after results: "Which of these keywords do you want to add to a campaign?"
  • Existing vs new campaign path followed correctly? Existing → group mapping confirmed. New → ASINs + budget collected before sp_campaign_preview.
  • Bids from get_suggested_bids? Not using CPC from analytics.
  • Preview shown before execute? preview_only: true called and confirmed before preview_only: false.

If any check fails, fix it before responding.


Versioning

v1 — July 2026. Initial draft (discarded — thresholds invented without user input).

v2 — July 2026. Full rebuild after 8-question elicitation. Key changes from v1: min_orders fixed to 2 (not invented); min_roas made dynamic (account_average_ROAS × 0.60, derived from snapshot); default date window set to last_30_days with auto-escalation to last_60_days if < 5 candidates; limit fixed to 250 rows; category grouping defined by Claude semantically (no pre-built table); post-harvest action flow fully specified (existing vs new campaign paths); trigger boundaries tightened (top search terms and wasting spend explicitly excluded).

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.