Skip to main content

Overview

The GeoAI_Analyzer class provides AI-powered content analysis using the Google Gemini API. It analyzes posts for SEO optimization, generates meta content, and tests API connectivity. This class uses the singleton pattern and includes the Encryption trait. Namespace: GeoAI\Core Location: includes/class-geoai-analyzer.php

Key Features

  • AI-powered SEO content auditing
  • Automatic analysis on post publish
  • Meta title and description generation
  • Answer engine optimization (Google AI Overviews, Perplexity, ChatGPT)
  • API connection testing
  • Background processing support via Action Scheduler

Public Methods

get_instance()

Returns the singleton instance of the analyzer class.
public static function get_instance()
Returns: GeoAI_Analyzer - The singleton instance Example:
$analyzer = \GeoAI\Core\GeoAI_Analyzer::get_instance();

analyze_post()

Analyzes a post using Google Gemini AI and returns comprehensive SEO audit data.
public function analyze_post( $post_id )
post_id
int
required
The ID of the post to analyze
Returns: array|WP_Error - Audit results or error object Response Structure:
{
  "scores": {
    "answerability": 85,
    "structure": 90,
    "trust": 75,
    "technical": 88,
    "total": 84
  },
  "issues": [
    {
      "id": "unique_id",
      "severity": "high",
      "msg": "Issue description",
      "quickFix": "fix_id"
    }
  ],
  "schema": {
    "article": true,
    "faq": false,
    "howto": false,
    "errors": []
  },
  "suggestions": {
    "titleOptions": ["Option 1", "Option 2"],
    "entities": ["Entity 1", "Entity 2"],
    "citations": ["https://example.com"]
  },
  "runAt": "2026-03-04T10:30:00+00:00"
}
Example:
$result = $analyzer->analyze_post( 123 );

if ( is_wp_error( $result ) ) {
    echo 'Error: ' . $result->get_error_message();
} else {
    echo 'Total Score: ' . $result['scores']['total'];
    echo 'Issues Found: ' . count( $result['issues'] );
}

maybe_auto_analyze()

Automatically analyzes post on save if auto-run is enabled.
public function maybe_auto_analyze( $post_id, $post )
post_id
int
required
The post ID being saved
post
WP_Post
required
The post object being saved
Hooks: save_post (priority 20) Behavior:
  • Only runs on published posts
  • Skips revisions and autosaves
  • Checks if auto-run is enabled in settings
  • Uses Action Scheduler if available for background processing

handle_background_audit()

Handles scheduled background audit tasks.
public function handle_background_audit( $post_id )
post_id
mixed
required
Post ID (can be int or array from scheduler)
Hooks: geoai_background_audit Example:
// Queue background audit
if ( function_exists( 'as_enqueue_async_action' ) ) {
    as_enqueue_async_action( 'geoai_background_audit', array( 'post_id' => 123 ) );
}

generate_meta_content()

Generates AI-powered meta title and description for a post.
public function generate_meta_content( $post_id )
post_id
int
required
The post ID to generate meta content for
Returns: array|WP_Error - Array with ‘title’ and ‘description’ keys, or error Response:
{
  "title": "Optimized Meta Title (50-60 chars)",
  "description": "Compelling meta description with call-to-action (150-160 chars)"
}
Example:
$meta = $analyzer->generate_meta_content( 123 );

if ( ! is_wp_error( $meta ) ) {
    update_post_meta( 123, '_geoai_title', $meta['title'] );
    update_post_meta( 123, '_geoai_meta_desc', $meta['description'] );
}

test_api_connection()

Tests the Google Gemini API connection.
public function test_api_connection( $override_key = null )
override_key
string
Optional API key to test (defaults to saved key)
Returns: array|WP_Error - Success message or error Example:
$result = $analyzer->test_api_connection();

if ( is_wp_error( $result ) ) {
    echo 'Connection failed: ' . $result->get_error_message();
} else {
    echo 'Success: ' . $result['message'];
}

Audit Metrics

Score Components

answerability
int
Score 0-100 measuring how well content answers user queries
structure
int
Score 0-100 measuring content organization and formatting
trust
int
Score 0-100 measuring authority and credibility signals
technical
int
Score 0-100 measuring technical SEO implementation
total
int
Overall score 0-100 (weighted average of components)

Issue Severity Levels

  • high - Critical issues that significantly impact SEO
  • med - Medium priority issues that should be addressed
  • low - Minor suggestions for improvement

API Configuration

Gemini API Endpoint

The analyzer uses the Gemini 1.5 Flash model:
https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent

Generation Settings

For Audits:
  • Temperature: 0.3 (more deterministic)
  • Top K: 40
  • Top P: 0.95
  • Max Tokens: 2048
  • Response Format: JSON
For Meta Generation:
  • Temperature: 0.7 (more creative)
  • Top K: 40
  • Top P: 0.95
  • Max Tokens: 512
  • Response Format: JSON

Storage and Caching

Post Meta Keys

_geoai_audit
string
JSON-encoded audit results from last analysis
_geoai_audit_timestamp
string
MySQL timestamp of last audit run

Retrieving Cached Audits

$audit_json = get_post_meta( $post_id, '_geoai_audit', true );
$audit = json_decode( $audit_json, true );

$timestamp = get_post_meta( $post_id, '_geoai_audit_timestamp', true );
echo 'Last audited: ' . $timestamp;

Error Handling

Common Error Codes

invalid_post
WP_Error
Post not found or invalid post ID
no_api_key
WP_Error
Google Gemini API key not configured in settings
api_error
WP_Error
API request failed or returned non-200 status code
parse_error
WP_Error
Failed to parse JSON response from Gemini API
invalid_data
WP_Error
API response missing required fields

Usage Examples

Manual Post Analysis

$analyzer = \GeoAI\Core\GeoAI_Analyzer::get_instance();
$result = $analyzer->analyze_post( 123 );

if ( ! is_wp_error( $result ) ) {
    // Display scores
    foreach ( $result['scores'] as $metric => $score ) {
        echo ucfirst( $metric ) . ': ' . $score . '/100 <br>';
    }
    
    // Display issues
    foreach ( $result['issues'] as $issue ) {
        echo '[' . strtoupper( $issue['severity'] ) . '] ' . $issue['msg'] . '<br>';
    }
}

Generate and Save Meta Content

$analyzer = \GeoAI\Core\GeoAI_Analyzer::get_instance();
$meta = $analyzer->generate_meta_content( 123 );

if ( ! is_wp_error( $meta ) ) {
    update_post_meta( 123, '_geoai_title', $meta['title'] );
    update_post_meta( 123, '_geoai_meta_desc', $meta['description'] );
    
    echo 'Meta content generated and saved!';
}

Test API Before Saving Key

$test_key = 'AIza...';
$analyzer = \GeoAI\Core\GeoAI_Analyzer::get_instance();
$result = $analyzer->test_api_connection( $test_key );

if ( ! is_wp_error( $result ) ) {
    update_option( 'geoai_api_key', $test_key );
    echo 'API key validated and saved!';
} else {
    echo 'Invalid API key: ' . $result->get_error_message();
}

Optimization Tips

Content Length Limits

  • Audit content: First 20,000 characters
  • Meta generation: First 5,000 characters
Large posts are automatically truncated to stay within API limits and reduce costs.

Background Processing

For better performance, install Action Scheduler:
composer require woocommerce/action-scheduler
The analyzer will automatically use it for background processing.

Build docs developers (and LLMs) love