Instruction: Explain the purpose and usage of the seo library based on its documentation.

Output:
![SEO for Craft CMS](resources/imgs/banner.jpg)

# SEO for Craft CMS

SEO for Craft does three things that will help your sites SEO, and does them really damn well:

1. [**Optimisation Field Type**](#the-field-type) - Helps your clients write better optimised copy, and manage other SEO meta.
2. [**Sitemap**](#the-sitemap) - Generates an always up-to-date XML sitemap automatically, with controls for customisation.
3. [**Redirects**](#the-redirects) - Quickly and easily manage 301 & 302 redirects. Especially useful when migrating from an old site.

[Click here for the **Craft 2** version.](https://github.com/ethercreative/seo/tree/v2)

### The Field Type

The SEO field type helps give users an idea of how their page will look in Google, and how their pages content scores when compared to a specific keyword.

The field type allows users to manage the meta of their page in one simple and easy to use input that has the added bonus of giving them an idea of how their page will show up in a Google search.

The field also contains a *Focus Keyword* input and *Page Score*. This is used to workout how relevant a keyword or phrase is to your entry and how well the page is likely to do in a search for that keyword.

The Page Score also contains a breakdown of your entries score, and tips on where it can be improved.

![SEO for Craft CMS](resources/imgs/fieldtype.jpg)

![SEO Social](resources/imgs/fieldtype-social.jpg)

![SEO Advanced](resources/imgs/fieldtype-advanced.jpg)

### The Sitemap

SEO for Craft boasts an extremely powerful, yet simple to use Sitemap manager. With automatic support for all your site’s sections and categories (with localisations taken into account), and the ability to easily add custom URLs (useful for public templates that aren’t content managed), keeping your sitemap up-to-date has never been easier.

With SEO for Craft’s sitemap manager you have complete control over what content you want to have appear on your sitemap as well as managing its change frequency and priority in your site.

![SEO Sitemap](resources/imgs/sitemap.jpg)

### The Redirects

When moving from your old, awful site to your shiny new Craft one, you’ll want to make sure that all your old pages are redirected to their new counterparts. Redirects are easy to manage with SEO for Craft.

SEO for Crafts redirect manager lets you easily add 301 & 302 redirects, with full .htaccess style regex support!

Redirects support [PCRE regex syntax](http://php.net/manual/en/reference.pcre.pattern.syntax.php). By default, all `/` and `?` not inside parenthesis are escaped. To prevent any escaping include the opening and closing forward slashes and flags: `/^blog$/i`. All redirects are given the insensitive flag, unless overwritten.

**Redirect Regex Example**
To redirect from `blog/2016/my-post` to `news/my-post` you would add the following redirect:

URI: `blog/([0-9]{4})/(.*)` To: `news/$2`

![SEO Redirects](resources/imgs/redirects.jpg)

## Installation & Usage

Clone this repo into `craft/plugins/seo`.

### Using Composer

**Easy way**

`composer require ether/seo`

**Alternative way**
1. Append `"ether/seo": "^3.1.0"` to the `require` hash of `composer.json`
2. `composer update`
3. Install via CP in `/admin/settings/plugins`

Before using the SEO field type, you’ll need to ensure all the settings are correct. You can find the settings under the SEO plugin menu in the sidebar, or via the plugin menu.

### Environment Setup

Ensure that your Production environment’s name is `production` (going with Craft’s convention). All other environments will get `X-Robots-Tag: none, noimageindex` headers added to every web response, to prevent search engines from indexing duplicate content.

Environment names are typically defined by an `ENVIRONMENT` environment variable.

### Fieldtype Usage

Replace your `title` tag, and any other SEO related meta tags with `{% hook "seo" %}`. That's it!

This assumes that you will be creating a variable call `seo` in your templates that will return either the SEO field or a custom SEO object (see below). You can modify the output of this hook by setting your own SEO Meta Template in the SEO Settings. You can [view the default template here](https://github.com/ethercreative/seo/blob/v3/src/templates/_seo/meta.twig).

### How meta output works (what the hook renders)

- **Automatic field detection**: The default meta template will try to find your SEO field automatically using `getSeoField('seo')`. If your field handle is not `seo`, pass it: `getSeoField('mySeoHandle')`. If nothing is found, it falls back to `craft.seo.custom(siteName, '')`.
- **Meta tags included**:
  - `<title>` from your SEO field’s title tokens or fallback
  - `<meta name="description">`
  - Open Graph tags (title, description, image, site name, locale, alternates)
  - Twitter Card tags (summary_large_image)
  - `<meta name="robots">` when applicable (see Robots section below)
  - `<link rel="canonical">`
- **Canonical also as a header**: In addition to the `<link rel="canonical">`, the plugin adds an HTTP `Link: <...>; rel="canonical"` header on every frontend response.

Tip: If you prefer to use an SEO object directly (e.g. for non-element templates), set a variable named `seo` in your template to `craft.seo.custom(...)` or include your element’s field value, and the hook will use it.

### Custom SEO Object

In some cases, you will not have access to an SEO field, but will want to set the page title, description, & socials. You can do this by creating a custom SEO object using the function below:

```twig
craft.seo.custom(
    'The Page Title',
    'The page description',
    null,

    // Social media - Any missing fields (excluding images) will be populated by the values above
    {
        twitter: { image: myImageField.first() },
        facebook: { title: '', description: '', image: myImageField.first() },
    }
)
```

alternatively pass an object as the first parameter. This will be used in place of an element.

```twig
craft.seo.custom(
    {
        title: 'The Page Title',
        someField: 'Hello world!',
    },
    'The page description'
)
```

All parameters are optional.

### Robots, noindex and robots.txt

- **Environment protection**
  - On any environment where `Craft::$app->env` is not `production`, every response gets an `X-Robots-Tag: none, noimageindex` header automatically to avoid accidental indexing of staging/dev. Keep production named exactly `production`.
  - When Craft’s `devMode` is enabled, the rendered `<meta name="robots">` will also be `none, noimageindex`.

- **Per‑entry robots directives (noindex, nofollow, etc.)**
  - In the entry editor, open your SEO field → Advanced tab → toggle the directives you need. Available switches include `noindex`, `nofollow`, `noarchive`, `nosnippet`, `notranslate`, `noimageindex`.
  - These map directly to the `<meta name="robots" content="...">` output. When present, the plugin also mirrors them via the `X-Robots-Tag` header.
  - If the element has an `expiryDate`, the plugin adds `unavailable_after: <date>` to the meta and headers automatically.

- **Global defaults**
  - Set the default robots directives in SEO → Settings → Robots. New entries inherit these defaults; you can override per entry in the Advanced tab.

- **robots.txt**
  - The plugin serves `robots.txt` at `/robots.txt` and renders it from the template you configure in SEO → Settings → Robots.
  - You can use any Craft Twig variables and a `seo` object that contains SEO settings. The default template includes your sitemap URL and blocks everything outside production, for example:

    ```twig
    {# Sitemap URL #}
    Sitemap: {{ url(seo.sitemapName ~ '.xml') }}

    {# Disallows #}
    {% if craft.app.config.env != 'production' %}
    User-agent: *
    Disallow: /
    {% else %}
    User-agent: *
    Disallow: /cpresources/
    {% endif %}
    ```

### Canonical URLs

- Set a canonical URL per entry in the SEO field → Advanced tab. Leave blank to fall back to the current page URL.
- Output is provided both as `<link rel="canonical" href="...">` and as an HTTP `Link` header, which some crawlers prefer.

### Using a custom meta template

- In SEO → Settings, set a custom Meta Template to fully control the markup the `{% hook "seo" %}` renders. The `seo` variable is a `SeoData` object with properties like `title`, `description`, `social.twitter`, `social.facebook`, `robots`, `canonical`, and `expiry` that you can use in your Twig.
- If you don’t provide a template, the built-in one at `seo/_seo/meta` is used.

## Upcoming Features

If you have a feature suggestion, [leave an issue](https://github.com/ethercreative/seo/issues) with the prefix `[FR]`.

---

Copyright © 2016 Ether Creative <hello@ethercreative.co.uk>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Instruction: Explain the purpose and usage of the python-seo-analyzer library based on its documentation.

Output:
Python SEO and GEO Analyzer
===========================

[![PyPI version](https://badge.fury.io/py/pyseoanalyzer.svg)](https://badge.fury.io/py/pyseoanalyzer)
[![Docker Pulls](https://img.shields.io/docker/pulls/sethblack/python-seo-analyzer.svg)](https://hub.docker.com/r/sethblack/python-seo-analyzer)

A modern SEO and GEO (Generative AI Engine Optimization or better AI Search Optimization) analysis tool that combines technical optimization and authentic human value. Beyond traditional site crawling and structure analysis, it uses AI to evaluate content's expertise signals, conversational engagement, and cross-platform presence. It helps you maintain strong technical foundations while ensuring your site demonstrates genuine authority and value to real users.

The AI features were heavily influenced by the clickbait-titled SEL article [A 13-point roadmap for thriving in the age of AI search](https://searchengineland.com/seo-roadmap-ai-search-449199).

Note About Python
-----------------

I've written quite a bit about the speed of Python and how there are very specific use cases where it isn't the best choice. I feel like crawling websites is definitely one of those cases. I wrote this tool in Python around 2010 to solve the very specific need of crawling some small HTML-only websites for startups I was working at. I'm excited to see how much it has grown and how many people are using it. I feel like Python SEO Analyzer is acceptable for most smaller use cases, but if you are looking for something better, I've built a much faster and more comprehensive tool [Black SEO Analyzer](https://github.com/sethblack/black-seo-analyzer).

-Seth

Installation
------------

### PIP

```
pip install pyseoanalyzer
```

### Docker

#### Using the Pre-built Image from Docker Hub

The easiest way to use the Docker image is to pull it directly from [Docker Hub](https://hub.docker.com/r/sethblack/python-seo-analyzer).

```bash
# Pull the latest image
docker pull sethblack/python-seo-analyzer:latest

# Run the analyzer (replace example.com with the target URL)
# The --rm flag automatically removes the container when it exits
docker run --rm sethblack/python-seo-analyzer http://example.com/

# Run with specific arguments (e.g., sitemap and HTML output)
# Note: If the sitemap is local, you'll need to mount it (see mounting example below)
docker run --rm sethblack/python-seo-analyzer http://example.com/ --sitemap /path/inside/container/sitemap.xml --output-format html

# Run with AI analysis (requires ANTHROPIC_API_KEY)
# Replace "your_api_key_here" with your actual Anthropic API key
docker run --rm -e ANTHROPIC_API_KEY="your_api_key_here" sethblack/python-seo-analyzer http://example.com/ --run-llm-analysis

# Save HTML output to your local machine
# This mounts the current directory (.) into /app/output inside the container.
# The output file 'results.html' will be saved in your current directory.
# The tool outputs JSON by default to stdout, so we redirect it for HTML.
# Since the ENTRYPOINT handles the command, we redirect the container's stdout.
# We need a shell inside the container to handle the redirection.
docker run --rm -v "$(pwd):/app/output" sethblack/python-seo-analyzer /bin/sh -c "seoanalyze http://example.com/ --output-format html > /app/output/results.html"
# Note for Windows CMD users: Use %cd% instead of $(pwd)
# docker run --rm -v "%cd%:/app/output" sethblack/python-seo-analyzer /bin/sh -c "seoanalyze http://example.com/ --output-format html > /app/output/results.html"
# Note for Windows PowerShell users: Use ${pwd} instead of $(pwd)
# docker run --rm -v "${pwd}:/app/output" sethblack/python-seo-analyzer /bin/sh -c "seoanalyze http://example.com/ --output-format html > /app/output/results.html"

# Mount a local sitemap file
# This mounts 'local-sitemap.xml' from the current directory to '/app/sitemap.xml' inside the container
docker run --rm -v "$(pwd)/local-sitemap.xml:/app/sitemap.xml" sethblack/python-seo-analyzer http://example.com/ --sitemap /app/sitemap.xml
# Adjust paths and Windows commands as needed (see volume mounting example above)

```

#### Building the Image Locally

You can also build the Docker image yourself from the source code. Make sure you have Docker installed and running.

```bash
# Clone the repository (if you haven't already)
# git clone https://github.com/sethblack/python-seo-analyzer.git
# cd python-seo-analyzer

# Build the Docker image (tag it as 'my-seo-analyzer' for easy reference)
docker build -t my-seo-analyzer .

# Run the locally built image
docker run --rm my-seo-analyzer http://example.com/

# Run with AI analysis using the locally built image
docker run --rm -e ANTHROPIC_API_KEY="your_api_key_here" my-seo-analyzer http://example.com/ --run-llm-analysis

# Run with HTML output saved locally using the built image
docker run --rm -v "$(pwd):/app/output" my-seo-analyzer /bin/sh -c "python-seo-analyzer http://example.com/ --output-format html > /app/output/results.html"
# Adjust Windows commands as needed (see volume mounting example above)
```

Command-line Usage
------------------

If you run without a sitemap it will start crawling at the homepage.

```sh
python-seo-analyzer http://www.domain.com/
```

Or you can specify the path to a sitmap to seed the urls to scan list.

```sh
seoanapython-seo-analyzerlyze http://www.domain.com/ --sitemap path/to/sitemap.xml
```

HTML output can be generated from the analysis instead of json.

```sh
python-seo-analyzer http://www.domain.com/ --output-format html
```

API
---

The `analyze` function returns a dictionary with the results of the crawl.

```python
from pyseoanalyzer import analyze

output = analyze(site, sitemap)

print(output)
```

In order to analyze heading tags (h1-h6) and other extra additional tags as well, the following options can be passed to the `analyze` function
```python
from pyseoanalyzer import analyze

output = analyze(site, sitemap, analyze_headings=True, analyze_extra_tags=True)

print(output)
```

By default, the `analyze` function analyzes all the existing inner links as well, which might be time consuming.
This default behaviour can be changed to analyze only the provided URL by passing the following option to the `analyze` function
```python
from pyseoanalyzer import analyze

output = analyze(site, sitemap, follow_links=False)

print(output)
```

Alternatively, you can run the analysis as a script from the seoanalyzer folder.

```sh
python -m seoanalyzer https://www.sethserver.com/ -f html > results.html
```

AI Optimization
---------------

The first pass of AI optimization features use Anthropic's `claude-3-sonnet-20240229` model to evaluate the content of the site. You will need to have an API key from [Anthropic](https://www.anthropic.com/) to use this feature. The API key needs to be set as the environment variable `ANTHROPIC_API_KEY`. I recommend using a `.env` file to set this variable. Once the API key is set, the AI optimization features can be enabled with the `--run-llm-analysis` flag.

Notes
-----

If you get `requests.exceptions.SSLError` at either the command-line or via the python-API, try using:
 - http://www.foo.bar

 **instead** of..

 -  https://www.foo.bar