File size: 3,288 Bytes
a74b879
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
"""Serper.dev client — Google SERP data for keyword ranking & competitor analysis."""
import os
import requests
from typing import List, Dict

SERPER_KEY = os.getenv("SERPER_KEY", "")
BASE_URL = "https://google.serper.dev"


def _key() -> str:
    """Return first available serper key, rotating across SERPER_KEY, SERPER_KEY_2, etc."""
    for suffix in ["", "_2", "_3", "_4", "_5"]:
        k = os.environ.get(f"SERPER_KEY{suffix}", "").strip()
        if k:
            return k
    return SERPER_KEY


def search(query: str, gl: str = "sa", hl: str = "ar", num: int = 10) -> Dict:
    """Run a Google search via serper.dev. Returns organic results + answerBox."""
    key = _key()
    if not key:
        return {"error": "no_serper_key"}
    try:
        r = requests.post(
            f"{BASE_URL}/search",
            headers={"X-API-KEY": key, "Content-Type": "application/json"},
            json={"q": query, "gl": gl, "hl": hl, "num": num},
            timeout=12,
        )
        r.raise_for_status()
        return r.json()
    except Exception as e:
        return {"error": str(e)}


def rank_check(site_url: str, keywords: List[str], gl: str = "sa", hl: str = "ar") -> List[Dict]:
    """
    For each keyword, search Google and find where site_url appears.
    Returns list of {kw, position, url, title, snippet, found}.
    """
    domain = site_url.replace("https://", "").replace("http://", "").rstrip("/").split("/")[0]
    results = []
    for kw in keywords[:10]:  # cap at 10 to save credits
        data = search(kw, gl=gl, hl=hl, num=10)
        organic = data.get("organic", [])
        found = None
        for item in organic:
            link = item.get("link", "")
            if domain in link:
                found = item
                break
        results.append({
            "kw": kw,
            "position": found["position"] if found else None,
            "url": found["link"] if found else None,
            "title": found["title"] if found else None,
            "snippet": found["snippet"] if found else None,
            "found": bool(found),
            "top_competitor": organic[0] if organic and not found else None,
        })
    return results


def competitor_serp(site_url: str, keyword: str, gl: str = "sa", hl: str = "ar") -> Dict:
    """
    Search for a keyword and return top 10 competitors with their positions.
    """
    domain = site_url.replace("https://", "").replace("http://", "").rstrip("/").split("/")[0]
    data = search(keyword, gl=gl, hl=hl, num=10)
    organic = data.get("organic", [])
    competitors = []
    site_position = None
    for item in organic:
        link = item.get("link", "")
        is_self = domain in link
        if is_self:
            site_position = item["position"]
        competitors.append({
            "position": item.get("position"),
            "title": item.get("title"),
            "link": link,
            "snippet": item.get("snippet", ""),
            "is_self": is_self,
        })
    return {
        "keyword": keyword,
        "site_position": site_position,
        "competitors": competitors,
        "answer_box": data.get("answerBox"),
        "knowledge_graph": data.get("knowledgeGraph"),
        "related_searches": data.get("relatedSearches", []),
    }