# CLI


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

------------------------------------------------------------------------

### seo_rat_sync

``` python

def seo_rat_sync(
    site_url:str, # e.g. "sc-domain:example.com"
    days:int=30, # how many days back to sync
    secrets:str='/home/runner/.config/seo_rat/client_secrets.json', token:str='./token.pickle'
):

```

*Sync GSC data for a site*

------------------------------------------------------------------------

### seo_rat_report

``` python

def seo_rat_report(
    website_id:int, # Website ID from the database
    days:int=90, # Days of GSC data to include
    insights:bool=False, # Include query trends and green keywords
):

```

*Generate SEO report for a website*

------------------------------------------------------------------------

### load_mapper

``` python

def load_mapper(
    domain:str
)->dict:

```

*Load and run the mapper for a given domain.*

------------------------------------------------------------------------

### seo_rat_audit

``` python

def seo_rat_audit(
    website_id:int, # Website ID from the database
    url:str='', # Page URL to audit
    file_path:str='', # Local file path to audit
    days:int=90, # Days of GSC data to include
    insights:bool=False, # Include trends and green keywords
):

```

*Audit a single page for SEO issues*

------------------------------------------------------------------------

### seo_rat_rank

``` python

def seo_rat_rank(
    website_id:int, # Website ID from the database
    keywords:str, # Comma-separated keywords to tracke
    range_type:str='entire_history', # Date range type
    country:str='', # Optional country code (e.g. 'sau')
):

```

*Check keyword rankings for a website*

------------------------------------------------------------------------

### print_rankings

``` python

def print_rankings(
    results:list
)->None:

```

*Print keyword rankings as a rich table.*

------------------------------------------------------------------------

### seo_rat_top_pages

``` python

def seo_rat_top_pages(
    website_id:int, # Website ID from the database
    range_type:str='entire_history', # Date range type
    limit:int=20, # Number of pages to show
    country:str='', # Optional country code (e.g. 'sau')
):

```

*Show top performing pages by clicks and impressions*

------------------------------------------------------------------------

### print_top_pages

``` python

def print_top_pages(
    rows:list, country:str | None=None
)->None:

```

*Print top pages as a rich table.*

------------------------------------------------------------------------

### seo_rat_wins

``` python

def seo_rat_wins(
    website_id:int, # Website ID from the database
    page_url:str='', # Optional page URL to filter
    range_type:str='entire_history', # Date range type
    min_impressions:int=100, # Minimum impressions threshold
    min_position:float=10.0, # Minimum avg position
    max_position:float=50.0, # Maximum avg position cutoff
    limit:int=20, # Number of results to show
    country:str='', # Optional country code
):

```

*Show high-impression, low-ranking keyword wins*

------------------------------------------------------------------------

### print_wins

``` python

def print_wins(
    rows:list
)->None:

```

*Print keyword wins as a rich table.*

------------------------------------------------------------------------

### seo_rat_canob

``` python

def seo_rat_canob(
    website_id:int, # Website ID from the database
    keyword:str='', # Specific keyword to check (omit for full site scan)
    similarity_threshold:float=0.8, # Similarity threshold for content groups
):

```

*Detect keyword cannibalization across pages*

------------------------------------------------------------------------

### print_canob_groups

``` python

def print_canob_groups(
    result:dict
)->None:

```

*Print content group duplicates as a rich table.*

------------------------------------------------------------------------

### print_canob_keyword

``` python

def print_canob_keyword(
    result:dict
)->None:

```

*Print keyword cannibalization result as a rich table.*

## Indexing

------------------------------------------------------------------------

### print_crawl_errors

``` python

def print_crawl_errors(
    pages:list
)->None:

```

*Call self as a function.*

------------------------------------------------------------------------

### print_index_report

``` python

def print_index_report(
    all_pages:list, grouped:dict
)->None:

```

*Call self as a function.*

------------------------------------------------------------------------

### print_index_check

``` python

def print_index_check(
    status:IndexStatus
)->None:

```

*Call self as a function.*

------------------------------------------------------------------------

### fmt_date

``` python

def fmt_date(
    dt:str | None
)->str:

```

*Format ISO datetime to YYYY-MM-DD.*

------------------------------------------------------------------------

### seo_rat_index_refresh

``` python

def seo_rat_index_refresh(
    website_id:int, # Website ID from the database
    sitemap_url:str, # Sitemap URL to fetch and re-check
):

```

*Refresh index status for all pages in a sitemap*

------------------------------------------------------------------------

### seo_rat_crawl_errors

``` python

def seo_rat_crawl_errors(
    website_id:int, # Website ID from the database
):

```

*Show pages with crawl or indexing issues*

------------------------------------------------------------------------

### seo_rat_index_report

``` python

def seo_rat_index_report(
    website_id:int, # Website ID from the database
    sitemap_url:str='', # Sitemap URL to refresh data (optional)
):

```

*Show index status report grouped by reason*

------------------------------------------------------------------------

### seo_rat_index_check

``` python

def seo_rat_index_check(
    website_id:int, # Website ID from the database
    page_url:str, # Page URL to inspect
):

```

*Check and store index status for a single page*

## Trends & Comparsion

------------------------------------------------------------------------

### seo_rat_trend

``` python

def seo_rat_trend(
    website_id:int, # Website ID from the database
    keyword:str, # Keyword to track
    range_type:str='entire_history', # Date range type
    months:int=3, # Months for last_months range type
    days:int=7, # Days for last_days range type
    country:str='', # Optional country code
):

```

*Show position trend for a keyword aggregated by period*

------------------------------------------------------------------------

### aggregate_by_period

``` python

def aggregate_by_period(
    rows:list, range_type:str, months:int=3
)->list:

```

*Aggregate daily rows by week or month depending on range.*

------------------------------------------------------------------------

### print_trend

``` python

def print_trend(
    keyword:str, rows:list
)->None:

```

*Call self as a function.*

------------------------------------------------------------------------

### seo_rat_add_website

``` python

def seo_rat_add_website(
    url:str, # Website URL (e.g., https://example.com)
    name:str, # Display name for the website
    site_type:str, # Type: quarto, astro, wordpress, etc.
    desc:str='', # Optional description
    lang:str='en', # Language code (e.g., en, ar)
    content_dir:str='', # Local path to content directory
    website_id:int=None, # ID to update existing website (omit to create new)
):

```

*Add a new website or update existing by ID*

------------------------------------------------------------------------

### seo_rat_list_websites

``` python

def seo_rat_list_websites(
    
):

```

*List all registered websites*

------------------------------------------------------------------------

### seo_rat_delete_website

``` python

def seo_rat_delete_website(
    website_id:int, # Website ID to delete
):

```

*Delete a website by ID (irreversible!)*

``` python
# Test: List all websites
seo_rat_list_websites()

# Test: Add a new website
seo_rat_add_website(
    url="https://test-example.com",
    name="Test Site",
    site_type="astro",
    desc="A test website",
    lang="en"
)
seo_rat_list_websites()
seo_rat_delete_website(5)
seo_rat_list_websites()
```

<pre style="white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace"><span style="font-style: italic">                        🌐 Websites                         </span>
┏━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━┓
┃<span style="font-weight: bold"> ID </span>┃<span style="font-weight: bold"> Name       </span>┃<span style="font-weight: bold"> URL                    </span>┃<span style="font-weight: bold"> Type   </span>┃<span style="font-weight: bold"> Lang </span>┃
┡━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━┩
│<span style="color: #7f7f7f; text-decoration-color: #7f7f7f">  1 </span>│<span style="color: #008080; text-decoration-color: #008080"> Awazly     </span>│ https://awazly.com     │<span style="color: #008000; text-decoration-color: #008000"> astro  </span>│  ar  │
│<span style="color: #7f7f7f; text-decoration-color: #7f7f7f">  2 </span>│<span style="color: #008080; text-decoration-color: #008080"> shelid     </span>│ https://shelid.com     │<span style="color: #008000; text-decoration-color: #008000"> astro  </span>│  ar  │
│<span style="color: #7f7f7f; text-decoration-color: #7f7f7f">  3 </span>│<span style="color: #008080; text-decoration-color: #008080"> emdadelgaz </span>│ https://emdadelgaz.com │<span style="color: #008000; text-decoration-color: #008000"> astro  </span>│  ar  │
│<span style="color: #7f7f7f; text-decoration-color: #7f7f7f">  4 </span>│<span style="color: #008080; text-decoration-color: #008080"> kareemai   </span>│ https://kareemai.com   │<span style="color: #008000; text-decoration-color: #008000"> quarto </span>│  ar  │
└────┴────────────┴────────────────────────┴────────┴──────┘
</pre>

<pre style="white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace"><span style="color: #008000; text-decoration-color: #008000">✅ Website added:</span> Test Site <span style="font-weight: bold">(</span>ID: <span style="color: #008080; text-decoration-color: #008080; font-weight: bold">5</span><span style="font-weight: bold">)</span>
</pre>

<pre style="white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace"><span style="font-style: italic">                         🌐 Websites                          </span>
┏━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━┓
┃<span style="font-weight: bold"> ID </span>┃<span style="font-weight: bold"> Name       </span>┃<span style="font-weight: bold"> URL                      </span>┃<span style="font-weight: bold"> Type   </span>┃<span style="font-weight: bold"> Lang </span>┃
┡━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━┩
│<span style="color: #7f7f7f; text-decoration-color: #7f7f7f">  1 </span>│<span style="color: #008080; text-decoration-color: #008080"> Awazly     </span>│ https://awazly.com       │<span style="color: #008000; text-decoration-color: #008000"> astro  </span>│  ar  │
│<span style="color: #7f7f7f; text-decoration-color: #7f7f7f">  2 </span>│<span style="color: #008080; text-decoration-color: #008080"> shelid     </span>│ https://shelid.com       │<span style="color: #008000; text-decoration-color: #008000"> astro  </span>│  ar  │
│<span style="color: #7f7f7f; text-decoration-color: #7f7f7f">  3 </span>│<span style="color: #008080; text-decoration-color: #008080"> emdadelgaz </span>│ https://emdadelgaz.com   │<span style="color: #008000; text-decoration-color: #008000"> astro  </span>│  ar  │
│<span style="color: #7f7f7f; text-decoration-color: #7f7f7f">  4 </span>│<span style="color: #008080; text-decoration-color: #008080"> kareemai   </span>│ https://kareemai.com     │<span style="color: #008000; text-decoration-color: #008000"> quarto </span>│  ar  │
│<span style="color: #7f7f7f; text-decoration-color: #7f7f7f">  5 </span>│<span style="color: #008080; text-decoration-color: #008080"> Test Site  </span>│ https://test-example.com │<span style="color: #008000; text-decoration-color: #008000"> astro  </span>│  en  │
└────┴────────────┴──────────────────────────┴────────┴──────┘
</pre>

<pre style="white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace"><span style="color: #008000; text-decoration-color: #008000">✅ Deleted:</span> Test Site <span style="font-weight: bold">(</span>ID: <span style="color: #008080; text-decoration-color: #008080; font-weight: bold">5</span><span style="font-weight: bold">)</span>
</pre>

<pre style="white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace"><span style="font-style: italic">                        🌐 Websites                         </span>
┏━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━┓
┃<span style="font-weight: bold"> ID </span>┃<span style="font-weight: bold"> Name       </span>┃<span style="font-weight: bold"> URL                    </span>┃<span style="font-weight: bold"> Type   </span>┃<span style="font-weight: bold"> Lang </span>┃
┡━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━┩
│<span style="color: #7f7f7f; text-decoration-color: #7f7f7f">  1 </span>│<span style="color: #008080; text-decoration-color: #008080"> Awazly     </span>│ https://awazly.com     │<span style="color: #008000; text-decoration-color: #008000"> astro  </span>│  ar  │
│<span style="color: #7f7f7f; text-decoration-color: #7f7f7f">  2 </span>│<span style="color: #008080; text-decoration-color: #008080"> shelid     </span>│ https://shelid.com     │<span style="color: #008000; text-decoration-color: #008000"> astro  </span>│  ar  │
│<span style="color: #7f7f7f; text-decoration-color: #7f7f7f">  3 </span>│<span style="color: #008080; text-decoration-color: #008080"> emdadelgaz </span>│ https://emdadelgaz.com │<span style="color: #008000; text-decoration-color: #008000"> astro  </span>│  ar  │
│<span style="color: #7f7f7f; text-decoration-color: #7f7f7f">  4 </span>│<span style="color: #008080; text-decoration-color: #008080"> kareemai   </span>│ https://kareemai.com   │<span style="color: #008000; text-decoration-color: #008000"> quarto </span>│  ar  │
└────┴────────────┴────────────────────────┴────────┴──────┘
</pre>

------------------------------------------------------------------------

### seo_rat_compare

``` python

def seo_rat_compare(
    website_id:int, # Website ID from the database
    start1:str, # First period start (YYYY-MM-DD)
    end1:str, # First period end (YYYY-MM-DD)
    start2:str, # Second period start (YYYY-MM-DD)
    end2:str, # Second period end (YYYY-MM-DD)
    page_url:str='', # Optional specific page URL to compare
):

```

*Compare GSC metrics between two date ranges, optionally for a specific
page*

------------------------------------------------------------------------

### print_comparison

``` python

def print_comparison(
    result:dict
)->None:

```

*Print date range comparison as a rich table.*

``` python
# Test: Compare two date ranges (use a real website_id from your DB)
seo_rat_compare(
    website_id=4,  # Change to real ID
    start1="2025-03-01",
    end1="2025-03-31",
    start2="2025-04-01",
    end2="2025-04-05",
    page_url="https://kareemai.com/"  # Change to real URL or omit for site-wide
)
```

<pre style="white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace"><span style="font-style: italic">                         📊 Page Comparison: https://kareemai.com/                          </span>
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
┃<span style="font-weight: bold"> Metric       </span>┃<span style="font-weight: bold"> 2025-03-01 to 2025-03-31 </span>┃<span style="font-weight: bold"> 2025-04-01 to 2025-04-05 </span>┃<span style="font-weight: bold">              Change </span>┃
┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
│ Clicks       │                        0 │                        0 │                  <span style="color: #800000; text-decoration-color: #800000">+0</span> │
│ Impressions  │                        3 │                        2 │                  <span style="color: #800000; text-decoration-color: #800000">-1</span> │
│ Avg Position │                    17.67 │                      4.5 │ <span style="color: #008000; text-decoration-color: #008000">-13.170000000000002</span> │
│ Avg CTR %    │                        0 │                        0 │                   - │
└──────────────┴──────────────────────────┴──────────────────────────┴─────────────────────┘
</pre>

------------------------------------------------------------------------

### seo_rat_country_breakdown

``` python

def seo_rat_country_breakdown(
    website_id:int, # Website ID from the database
    range_type:str='last_month', # Date range type
    start_date:str='', # Custom start date (YYYY-MM-DD)
    end_date:str='', # Custom end date (YYYY-MM-DD)
    page_url:str='', # Optional specific page URL to filter
    limit:int=20, # Number of top countries to show
):

```

*Show traffic breakdown by country, optionally for a specific page*

------------------------------------------------------------------------

### print_country_breakdown

``` python

def print_country_breakdown(
    rows:list
)->None:

```

*Print country breakdown as a rich table.*

``` python
# Test: Country breakdown (use a real website_id from your DB)
seo_rat_country_breakdown(
    website_id=1,  # Change to real ID
    limit=20
)

seo_rat_country_breakdown(
    website_id=4,  # Change to real ID
    range_type="last_month",
    page_url="https://kareemai.com/blog/posts/speech_recognition/muaalm_quran_chance.html",  # Change to real URL or omit for site-wide
    limit=10  # Show top 10 countries
)
```

<pre style="white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace"><span style="font-style: italic">                   🌍 Traffic by Country                    </span>
┏━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━┓
┃<span style="font-weight: bold"> Country </span>┃<span style="font-weight: bold">     Clicks </span>┃<span style="font-weight: bold"> Impressions </span>┃<span style="font-weight: bold"> Avg Position </span>┃<span style="font-weight: bold">  CTR </span>┃
┡━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━┩
│<span style="color: #008080; text-decoration-color: #008080"> sau     </span>│ 72 (85.7%) │      18,763 │         25.6 │ 0.3% │
│<span style="color: #008080; text-decoration-color: #008080"> egy     </span>│   8 (9.5%) │       2,440 │         23.8 │ 0.3% │
│<span style="color: #008080; text-decoration-color: #008080"> lby     </span>│   1 (1.2%) │          43 │          5.2 │ 2.9% │
│<span style="color: #008080; text-decoration-color: #008080"> kwt     </span>│   1 (1.2%) │         403 │         17.1 │ 0.5% │
│<span style="color: #008080; text-decoration-color: #008080"> esp     </span>│   1 (1.2%) │          15 │         20.3 │ 6.7% │
│<span style="color: #008080; text-decoration-color: #008080"> are     </span>│   1 (1.2%) │          94 │         19.1 │ 1.2% │
│<span style="color: #008080; text-decoration-color: #008080"> zaf     </span>│   0 (0.0%) │           1 │          9.0 │ 0.0% │
│<span style="color: #008080; text-decoration-color: #008080"> yem     </span>│   0 (0.0%) │         119 │          7.0 │ 0.0% │
│<span style="color: #008080; text-decoration-color: #008080"> vnm     </span>│   0 (0.0%) │          17 │         40.0 │ 0.0% │
│<span style="color: #008080; text-decoration-color: #008080"> uzb     </span>│   0 (0.0%) │           1 │          6.0 │ 0.0% │
│<span style="color: #008080; text-decoration-color: #008080"> usa     </span>│   0 (0.0%) │         111 │         21.3 │ 0.0% │
│<span style="color: #008080; text-decoration-color: #008080"> ukr     </span>│   0 (0.0%) │           1 │         49.0 │ 0.0% │
│<span style="color: #008080; text-decoration-color: #008080"> uga     </span>│   0 (0.0%) │           1 │         12.0 │ 0.0% │
│<span style="color: #008080; text-decoration-color: #008080"> twn     </span>│   0 (0.0%) │           1 │          8.0 │ 0.0% │
│<span style="color: #008080; text-decoration-color: #008080"> tur     </span>│   0 (0.0%) │          19 │          7.6 │ 0.0% │
│<span style="color: #008080; text-decoration-color: #008080"> tun     </span>│   0 (0.0%) │           6 │          5.5 │ 0.0% │
│<span style="color: #008080; text-decoration-color: #008080"> tha     </span>│   0 (0.0%) │           1 │         42.0 │ 0.0% │
│<span style="color: #008080; text-decoration-color: #008080"> tcd     </span>│   0 (0.0%) │           2 │          6.0 │ 0.0% │
│<span style="color: #008080; text-decoration-color: #008080"> syr     </span>│   0 (0.0%) │          88 │          5.1 │ 0.0% │
│<span style="color: #008080; text-decoration-color: #008080"> swe     </span>│   0 (0.0%) │           2 │         19.5 │ 0.0% │
└─────────┴────────────┴─────────────┴──────────────┴──────┘
</pre>

<pre style="white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace">
<span style="color: #7f7f7f; text-decoration-color: #7f7f7f">Total: </span><span style="color: #7fbfbf; text-decoration-color: #7fbfbf; font-weight: bold">84</span><span style="color: #7f7f7f; text-decoration-color: #7f7f7f"> clicks across </span><span style="color: #7fbfbf; text-decoration-color: #7fbfbf; font-weight: bold">20</span><span style="color: #7f7f7f; text-decoration-color: #7f7f7f"> countries</span>
</pre>

<pre style="white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace"><span style="color: #808000; text-decoration-color: #808000">No country data found</span>
</pre>
