# thinkrank/1.0.0/src/admin/utils/optimizationHelpers.js

ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console &amp; Local SEO, version 1.0.0. 317 lines.

- Page: https://pluginprobe.com/plugins/thinkrank/1.0.0/code/src/admin/utils/optimizationHelpers.js
- Raw: https://pluginprobe.com/plugins/thinkrank/1.0.0/raw/src/admin/utils/optimizationHelpers.js
- Modified: 2025-08-10T07:57:44+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/thinkrank/1.0.0/code/src/admin/utils/optimizationHelpers.js#L10-L20`.

```javascript
/**
 * Optimization Helpers Utility
 * 
 * Standardized optimization workflow helpers extracted from Site Identity patterns.
 * Provides reusable functions for AI optimization, rule-based optimization,
 * validation, and result processing across all Essential SEO tabs.
 * 
 * @package ThinkRank
 * @since 1.0.0
 */

import { __ } from '@wordpress/i18n';

/**
 * Create optimization handler with consistent error handling and state management
 * 
 * @param {string} apiPath API endpoint path for optimization
 * @param {Function} setOptimizing State setter for optimization loading state
 * @param {Function} setNotice State setter for notice display
 * @param {Object} options Handler configuration options
 * @param {boolean} options.enableAutoApply Enable automatic application of results (default: false)
 * @param {Function} options.onSuccess Success callback function
 * @param {Function} options.onError Error callback function
 * @param {Function} options.onComplete Completion callback function (always called)
 * 
 * @return {Function} Optimization handler function
 */
export const createOptimizationHandler = (apiPath, setOptimizing, setNotice, options = {}) => {
    const {
        enableAutoApply = false,
        onSuccess,
        onError,
        onComplete
    } = options;

    return async (data, optimizationOptions = {}) => {
        try {
            setOptimizing(true);
            setNotice(null);

            const response = await fetch(apiPath, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-WP-Nonce': window.wpApiSettings?.nonce || ''
                },
                body: JSON.stringify({
                    data,
                    options: {
                        ...optimizationOptions,
                        autoApply: enableAutoApply
                    }
                })
            });

            const result = await response.json();

            if (result.success) {
                setNotice({
                    status: 'success',
                    message: __('Optimization completed successfully!', 'thinkrank')
                });

                if (onSuccess) {
                    onSuccess(result.data);
                }

                return result.data;
            } else {
                throw new Error(result.error || 'Optimization failed');
            }
        } catch (error) {
            console.error('Optimization error:', error);
            
            const errorMessage = getOptimizationErrorMessage(error);
            setNotice({
                status: 'error',
                message: errorMessage
            });

            if (onError) {
                onError(error);
            }

            throw error;
        } finally {
            setOptimizing(false);
            
            if (onComplete) {
                onComplete();
            }
        }
    };
};

/**
 * Get user-friendly error message for optimization failures
 * Extracted from Site Identity error handling patterns
 * 
 * @param {Error} error Error object
 * @return {string} User-friendly error message
 */
export const getOptimizationErrorMessage = (error) => {
    if (!error.message) {
        return __('Optimization failed. Please try again.', 'thinkrank');
    }

    const message = error.message.toLowerCase();

    if (message.includes('api key')) {
        return __('AI optimization requires an API key. Please configure your OpenAI or Claude API key in ThinkRank settings.', 'thinkrank');
    }

    if (message.includes('rate limit')) {
        return __('AI service rate limit reached. Please try again in a few minutes.', 'thinkrank');
    }

    if (message.includes('network') || message.includes('fetch')) {
        return __('Network error. Please check your connection and try again.', 'thinkrank');
    }

    if (message.includes('permission') || message.includes('unauthorized')) {
        return __('Permission denied. Please check your user permissions.', 'thinkrank');
    }

    if (message.includes('timeout')) {
        return __('Request timed out. Please try again.', 'thinkrank');
    }

    if (message.includes('quota') || message.includes('limit exceeded')) {
        return __('API quota exceeded. Please check your API usage limits.', 'thinkrank');
    }

    return __('Optimization failed. Please try again.', 'thinkrank');
};

/**
 * Create validation handler with consistent patterns
 * 
 * @param {string} apiPath API endpoint path for validation
 * @param {Function} setValidating State setter for validation loading state
 * @param {Function} setNotice State setter for notice display
 * @param {Object} options Handler configuration options
 * 
 * @return {Function} Validation handler function
 */
export const createValidationHandler = (apiPath, setValidating, setNotice, options = {}) => {
    const { onSuccess, onError, onComplete } = options;

    return async (data, validationOptions = {}) => {
        try {
            setValidating(true);
            setNotice(null);

            const response = await fetch(apiPath, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-WP-Nonce': window.wpApiSettings?.nonce || ''
                },
                body: JSON.stringify({
                    data,
                    options: validationOptions
                })
            });

            const result = await response.json();

            if (result.success) {
                const status = result.data.valid ? 'success' : 'warning';
                const message = result.data.message || __('Validation completed.', 'thinkrank');

                setNotice({
                    status,
                    message
                });

                if (onSuccess) {
                    onSuccess(result.data);
                }

                return result.data;
            } else {
                throw new Error(result.error || 'Validation failed');
            }
        } catch (error) {
            console.error('Validation error:', error);
            
            setNotice({
                status: 'error',
                message: __('Validation failed. Please try again.', 'thinkrank')
            });

            if (onError) {
                onError(error);
            }

            throw error;
        } finally {
            setValidating(false);
            
            if (onComplete) {
                onComplete();
            }
        }
    };
};

/**
 * Process optimization results and extract actionable data
 * 
 * @param {Object} results Optimization results from API
 * @param {Object} options Processing options
 * @param {Array} options.requiredFields Required fields in results
 * @param {Function} options.transformer Result transformation function
 * 
 * @return {Object} Processed results
 */
export const processOptimizationResults = (results, options = {}) => {
    const { requiredFields = [], transformer } = options;

    if (!results || typeof results !== 'object') {
        throw new Error('Invalid optimization results');
    }

    // Check for required fields
    for (const field of requiredFields) {
        if (!(field in results)) {
            throw new Error(`Missing required field: ${field}`);
        }
    }

    // Apply transformation if provided
    if (transformer && typeof transformer === 'function') {
        return transformer(results);
    }

    return results;
};

/**
 * Create debounced optimization function to prevent rapid-fire requests
 * 
 * @param {Function} optimizationFn Optimization function to debounce
 * @param {number} delay Debounce delay in milliseconds (default: 1000)
 * 
 * @return {Function} Debounced optimization function
 */
export const createDebouncedOptimization = (optimizationFn, delay = 1000) => {
    let timeoutId;

    return (...args) => {
        clearTimeout(timeoutId);
        
        timeoutId = setTimeout(() => {
            optimizationFn(...args);
        }, delay);
    };
};

/**
 * Optimization type configurations
 * Extracted from Site Identity getOptimizationButtonConfig patterns
 */
export const OPTIMIZATION_TYPES = {
    AI: {
        type: 'ai',
        label: __('AI Optimize', 'thinkrank'),
        loadingLabel: __('AI Optimizing...', 'thinkrank'),
        className: 'thinkrank-btn-ai'
    },
    RULE: {
        type: 'rule',
        label: __('Optimize', 'thinkrank'),
        loadingLabel: __('Optimizing...', 'thinkrank'),
        className: 'thinkrank-btn-rule'
    },
    VALIDATE: {
        type: 'validate',
        label: __('Validate', 'thinkrank'),
        loadingLabel: __('Validating...', 'thinkrank'),
        className: 'thinkrank-btn-validate'
    },
    TEST: {
        type: 'test',
        label: __('Test Connection', 'thinkrank'),
        loadingLabel: __('Testing...', 'thinkrank'),
        className: 'thinkrank-btn-test'
    },
    GENERATE: {
        type: 'generate',
        label: __('Generate', 'thinkrank'),
        loadingLabel: __('Generating...', 'thinkrank'),
        className: 'thinkrank-btn-generate'
    }
};

/**
 * Get optimization configuration by type
 * 
 * @param {string} type Optimization type
 * @return {Object} Optimization configuration
 */
export const getOptimizationConfig = (type) => {
    return OPTIMIZATION_TYPES[type.toUpperCase()] || OPTIMIZATION_TYPES.RULE;
};

export default {
    createOptimizationHandler,
    createValidationHandler,
    createDebouncedOptimization,
    processOptimizationResults,
    getOptimizationErrorMessage,
    getOptimizationConfig,
    OPTIMIZATION_TYPES
};

```
