# Analyzers reference

TurboSEO provides 7 Python analyzer modules for content analysis. All modules return Pydantic models for easy serialization and validation.

## Installation

```python
pip install turboseo
```

## Modules

### writing_standards

Detects AI writing patterns based on Wikipedia guidelines.

```python
from turboseo.analyzers.writing_standards import analyze_writing_standards

content = open("article.md").read()
result = analyze_writing_standards(content, strict=False)

print(f"Score: {result.score}/100")
print(f"Grade: {result.grade}")
print(f"Issues: {len(result.issues)}")
```

**Function signature:**
```python
def analyze_writing_standards(
    content: str,
    strict: bool = False
) -> WritingStandardsResult
```

**Parameters:**
- `content` - Text to analyze
- `strict` - Use stricter scoring thresholds (default: False)

**Returns `WritingStandardsResult`:**
```python
class WritingStandardsResult(BaseModel):
    score: int           # 0-100
    grade: str           # A, B, C, D, F
    issues: list[WritingIssue]
    summary: dict[str, int]  # Count by category
    word_count: int

class WritingIssue(BaseModel):
    line: int
    column: int
    text: str
    category: str        # vocabulary, puffery, superficial, structural, formatting
    severity: str        # high, medium, low
    suggestion: str
```

---

### readability

Calculates readability metrics.

```python
from turboseo.analyzers.readability import analyze_readability

result = analyze_readability(content)

print(f"Flesch Reading Ease: {result.flesch_reading_ease}")
print(f"Grade Level: {result.flesch_kincaid_grade}")
print(f"Passive Voice: {result.passive_voice_ratio * 100:.1f}%")
```

**Function signature:**
```python
def analyze_readability(content: str) -> ReadabilityResult
```

**Returns `ReadabilityResult`:**
```python
class ReadabilityResult(BaseModel):
    score: int                    # 0-100 composite score
    grade: str                    # A-F
    status: str                   # excellent, good, needs_improvement, poor
    flesch_reading_ease: float    # 0-100, higher = easier
    flesch_kincaid_grade: float   # US grade level
    gunning_fog: float            # Years of education needed
    smog_index: float             # Simple Measure of Gobbledygook
    word_count: int
    sentence_count: int
    paragraph_count: int
    avg_sentence_length: float
    avg_paragraph_length: float
    long_sentence_count: int      # >25 words
    very_long_sentence_count: int # >35 words
    complex_word_count: int       # 3+ syllables
    complex_word_ratio: float
    passive_voice_count: int
    passive_voice_ratio: float
    transition_word_count: int
    recommendations: list[str]
```

---

### keywords

Analyzes keyword usage and placement.

```python
from turboseo.analyzers.keywords import analyze_keywords

result = analyze_keywords(
    content,
    primary_keyword="podcast hosting",
    secondary_keywords=["best podcast host", "podcast platforms"],
    target_density=1.5
)

print(f"Density: {result.primary.density:.1f}%")
print(f"In H1: {result.primary.placements.in_h1}")
print(f"Stuffing Risk: {result.stuffing_risk.level}")
```

**Function signature:**
```python
def analyze_keywords(
    content: str,
    primary_keyword: str,
    secondary_keywords: list[str] | None = None,
    target_density: float = 1.5
) -> KeywordResult
```

**Returns `KeywordResult`:**
```python
class KeywordResult(BaseModel):
    primary: PrimaryKeywordAnalysis
    secondary: list[SecondaryKeywordAnalysis]
    distribution: list[SectionDistribution]
    stuffing_risk: StuffingRisk
    recommendations: list[str]

class PrimaryKeywordAnalysis(BaseModel):
    keyword: str
    exact_matches: int
    partial_matches: int
    density: float
    target_density: float
    status: str  # optimal, slightly_low, slightly_high, too_low, too_high
    placements: KeywordPlacements

class KeywordPlacements(BaseModel):
    in_h1: bool
    in_first_100_words: bool
    in_conclusion: bool
    h2_count: int
    h2_with_keyword: int
```

---

### seo_score

Composite SEO scoring across all dimensions.

```python
from turboseo.analyzers.seo_score import analyze_seo

result = analyze_seo(
    content,
    primary_keyword="podcast hosting",
    secondary_keywords=["best podcast host"],
    meta_title="Best Podcast Hosting 2024",
    meta_description="Compare top podcast hosting platforms..."
)

print(f"Overall: {result.overall_score}/100 ({result.grade})")
print(f"Publishing Ready: {result.publishing_ready}")

for cat, data in result.categories.items():
    print(f"  {cat}: {data.score} (weight: {data.weight:.0%})")
```

**Function signature:**
```python
def analyze_seo(
    content: str,
    primary_keyword: str | None = None,
    secondary_keywords: list[str] | None = None,
    meta_title: str | None = None,
    meta_description: str | None = None
) -> SEOResult
```

**Category weights:**
| Category | Weight |
|----------|--------|
| human_writing | 25% |
| keywords | 20% |
| content | 20% |
| readability | 15% |
| meta | 10% |
| structure | 10% |

**Returns `SEOResult`:**
```python
class SEOResult(BaseModel):
    overall_score: int
    grade: str
    publishing_ready: bool
    categories: dict[str, CategoryScore]
    critical_issues: list[str]
    warnings: list[str]
    suggestions: list[str]
    word_count: int
    h1_count: int
    h2_count: int
    h3_count: int
```

---

### search_intent

Classifies search query intent.

```python
from turboseo.analyzers.search_intent import classify_intent

result = classify_intent("best podcast hosting platforms 2024")

print(f"Intent: {result.primary_intent}")
print(f"Confidence: {result.confidence}")
```

**Function signature:**
```python
def classify_intent(query: str) -> IntentResult
```

**Intent types:**
- `informational` - Seeking information (how, what, why)
- `commercial` - Comparing options (best, review, vs)
- `transactional` - Ready to act (buy, sign up, download)
- `navigational` - Looking for specific site/page

---

### content_fetcher

Fetches and parses content from URLs.

```python
from turboseo.analyzers.content_fetcher import fetch_content

result = fetch_content("https://example.com/article")

print(f"Title: {result.title}")
print(f"Word count: {result.word_count}")
print(f"Internal links: {len(result.internal_links)}")
```

**Function signature:**
```python
def fetch_content(url: str) -> FetchResult
```

**Returns `FetchResult`:**
```python
class FetchResult(BaseModel):
    url: str
    title: str
    content: str
    word_count: int
    headings: list[Heading]
    internal_links: list[Link]
    external_links: list[Link]
    images: list[Image]
    meta_title: str | None
    meta_description: str | None
```

---

### content_length

Benchmarks content length against targets.

```python
from turboseo.analyzers.content_length import analyze_length

result = analyze_length(content, content_type="blog_post")

print(f"Word count: {result.word_count}")
print(f"Target: {result.target_min}-{result.target_max}")
print(f"Status: {result.status}")
```

**Function signature:**
```python
def analyze_length(
    content: str,
    content_type: str = "blog_post"
) -> LengthResult
```

**Content type targets:**
| Type | Target Words |
|------|-------------|
| blog_post | 1500-2500 |
| pillar_page | 3000-5000 |
| product_page | 500-1000 |
| landing_page | 300-700 |

## Error handling

All analyzers handle empty or invalid input gracefully:

```python
result = analyze_writing_standards("")
# Returns score=100, grade="A", issues=[], word_count=0

result = analyze_writing_standards(None)
# Raises TypeError
```

## JSON serialization

All result models support JSON export:

```python
result = analyze_writing_standards(content)

# To dict
data = result.model_dump()

# To JSON string
import json
json_str = json.dumps(result.model_dump(), indent=2)

# From dict
from turboseo.analyzers.writing_standards import WritingStandardsResult
restored = WritingStandardsResult(**data)
```
