Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Optimize websites for both traditional search engines (Google, Bing) and AI engines (ChatGPT, Perplexity, Gemini)
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
scripts/competitor_gap.py
1#!/usr/bin/env python32"""3Competitor keyword gap analysis using DataForSEO API4Finds keywords where competitor ranks but you don't56Usage: python3 scripts/competitor_gap.py "opc.dev" "claudemarketplaces.com" --limit 507"""8import argparse9from dataforseo_api import api_post, get_result, format_count101112def main():13parser = argparse.ArgumentParser(description="Competitor keyword gap analysis")14parser.add_argument("my_domain", help="Your domain (without https://)")15parser.add_argument("competitor_domain", help="Competitor domain (without https://)")16parser.add_argument("--location", "-loc", type=int, default=2840,17help="Location code (default: 2840 = US)")18parser.add_argument("--limit", "-l", type=int, default=50,19help="Max results (default: 50)")20args = parser.parse_args()2122data = [{23"target1": args.my_domain,24"target2": args.competitor_domain,25"location_code": args.location,26"language_code": "en",27"intersections": False, # Only show keywords where target2 ranks but target1 doesn't28"limit": args.limit29}]3031response = api_post("dataforseo_labs/google/domain_intersection/live", data)32results = get_result(response)3334print(f"my_domain: {args.my_domain}")35print(f"competitor_domain: {args.competitor_domain}")36print(f"location: {args.location}")37print()3839if results:40all_items = []41for result in results:42items = result.get("items", [])43if items:44all_items.extend(items)4546if not all_items:47print("No keyword gaps found")48return4950# Results show keywords where competitor ranks but you don't51print(f"keyword_gaps[{len(all_items)}]{{keyword,volume,difficulty,comp_position}}:")52for item in all_items:53kw_data = item.get("keyword_data", {})54keyword = kw_data.get("keyword", "N/A")5556# Get search volume from keyword_info57kw_info = kw_data.get("keyword_info", {})58volume = format_count(kw_info.get("search_volume", 0))5960# Get keyword difficulty61difficulty = kw_info.get("competition_level", "N/A")6263# Get competitor's ranking position64# When intersections=false, we get keywords where only second_domain (competitor) ranks65comp_element = item.get("second_domain_serp_element")66if comp_element and isinstance(comp_element, dict):67comp_pos = comp_element.get("rank_absolute", comp_element.get("rank_group", "N/A"))68else:69comp_pos = "N/A"7071print(f" {keyword},{volume},{difficulty},{comp_pos}")72else:73print("No keyword gaps found")7475print()76print("Tip: Focus on keywords with high volume and low difficulty where competitor ranks in top 10")777879if __name__ == "__main__":80main()81