Plugin Directory

Changeset 3257427


Ignore:
Timestamp:
03/17/2025 11:51:42 PM (11 months ago)
Author:
designful
Message:

Update to version 1.0.9 from GitHub

Location:
seo-ai-audit-tool
Files:
14 edited
1 copied

Legend:

Unmodified
Added
Removed
  • seo-ai-audit-tool/tags/1.0.9/assets/js/seoaudp-backlinks-analyzer.js

    r3252394 r3257427  
    16861686        }
    16871687
     1688        // Get branded keywords for display
     1689        let brandedKeywords = [];
     1690        try {
     1691            const storedBrandedKeywords = localStorage.getItem('seoaudp_branded_keywords');
     1692            if (storedBrandedKeywords) {
     1693                brandedKeywords = JSON.parse(storedBrandedKeywords);
     1694            }
     1695        } catch (error) {
     1696            console.error('Error parsing branded keywords:', error);
     1697        }
     1698       
     1699        // Branded keywords label
     1700        const brandedKeywordsLabel = Array.isArray(brandedKeywords) && brandedKeywords.length > 0
     1701            ? `Branded KWs (${brandedKeywords.join(', ')})`
     1702            : 'Branded KWs';
     1703
    16881704        // First, ensure all orders have page IDs
    16891705        const ordersWithPageIds = orders.map(async order => {
     
    17601776                    const brandedKwLinks = brandedKwKeyword ? (brandedKwKeyword.desiredLinks || 1) : '';
    17611777                   
     1778                    // Get the current branded keywords from localStorage
     1779                    let brandedKeywordsLabel = 'Branded KWs';
     1780                    try {
     1781                        const storedBrandedKeywords = localStorage.getItem('seoaudp_branded_keywords');
     1782                        if (storedBrandedKeywords) {
     1783                            const brandedKeywords = JSON.parse(storedBrandedKeywords);
     1784                            if (Array.isArray(brandedKeywords) && brandedKeywords.length > 0) {
     1785                                brandedKeywordsLabel = `Branded KWs (${brandedKeywords.join(', ')})`;
     1786                            }
     1787                        }
     1788                    } catch (error) {
     1789                        console.error('Error parsing branded keywords:', error);
     1790                    }
     1791                   
    17621792                    // Add first row with URL, Naked URL keyword and delete button (with top border for group)
    17631793                    html += `
     
    17821812                                <td></td>
    17831813                                <td></td>
    1784                                 <td class="seoaudp-keyword-cell">Branded KWs</td>
     1814                                <td class="seoaudp-keyword-cell">${brandedKeywordsLabel}</td>
    17851815                                <td>${brandedKwLinks}</td>
    17861816                                <td class="seoaudp-order-actions">
     
    20262056    // Update the showKeywordEditor method to handle multiple keywords
    20272057    async showKeywordEditor(cell, orderId, pageUrl) {
     2058        // First create a loading indicator
     2059        cell.innerHTML = `<span class="seoaudp-loading-spinner">Loading...</span>`;
     2060       
    20282061        try {
    2029             // Store the original content
    2030             const originalContent = cell.innerHTML;
    2031             cell.setAttribute('data-original-content', originalContent);
    2032            
    2033             // Get the row
    2034             const row = cell.closest('tr');
    2035            
    2036             // Try to get page ID directly from the row
    2037             let pageId = row.getAttribute('data-page-id');
    2038            
    2039             // If not found, try to get it from the hidden input
     2062            // Get page ID from URL
     2063            let pageId = await this.getPageIdFromUrl(pageUrl);
     2064           
    20402065            if (!pageId) {
    2041                 const hiddenInput = row.querySelector('.seoaudp-page-id-hidden');
    2042                 if (hiddenInput) {
    2043                     pageId = hiddenInput.value;
    2044                 }
    2045             }
    2046            
    2047             // If still not found, try to get it from the URL
    2048             if (!pageId) {
    2049                 // Make sure we have a valid URL
    2050                 if (!pageUrl) {
    2051                     const anchor = row.querySelector('a');
    2052                     if (anchor) {
    2053                         pageUrl = anchor.href;
    2054                     } else {
    2055                         // Try to get URL from data attribute
    2056                         pageUrl = row.getAttribute('data-page-url');
    2057                         if (!pageUrl) {
    2058                             // Try to get URL from a sibling row that has an anchor
    2059                             const siblingWithAnchor = row.parentElement.querySelector('tr[data-page-url] a');
    2060                             if (siblingWithAnchor) {
    2061                                 pageUrl = siblingWithAnchor.href;
    2062                             } else {
    2063                                 console.error('Could not determine page URL');
    2064                                 alert('Could not determine page URL for this row');
    2065                                 return;
    2066                             }
    2067                         }
     2066                throw new Error('Could not determine page ID');
     2067            }
     2068           
     2069            // Get all keywords for this page
     2070            const keywordsData = await this.getKeywordsForPage(pageId);
     2071           
     2072            // Get current keywords in the row
     2073            const currentKeywords = this.getCurrentKeywords(cell);
     2074           
     2075            // Get branded keywords label with parentheses if available
     2076            let brandedKeywordsLabel = 'Branded KWs';
     2077            try {
     2078                const storedBrandedKeywords = localStorage.getItem('seoaudp_branded_keywords');
     2079                if (storedBrandedKeywords) {
     2080                    const brandedKeywords = JSON.parse(storedBrandedKeywords);
     2081                    if (Array.isArray(brandedKeywords) && brandedKeywords.length > 0) {
     2082                        brandedKeywordsLabel = `Branded KWs (${brandedKeywords.join(', ')})`;
    20682083                    }
    20692084                }
    2070                
    2071                 // Get page ID from URL
    2072                 pageId = await this.getPageIdFromUrl(pageUrl);
    2073             }
    2074            
    2075             if (!pageId) {
    2076                 console.error('Could not determine page ID');
    2077                 alert('Could not determine page ID for this row');
    2078                 return;
    2079             }
    2080            
    2081             // Get keywords for this page
    2082             const keywordsData = await this.getKeywordsForPage(pageId);
    2083             if (!keywordsData) {
    2084                 alert('No keywords found for this page');
    2085                 return;
    2086             }
    2087            
    2088             // Get all currently selected keywords for this order
    2089             const currentKeywords = this.getCurrentKeywords(cell);
    2090            
    2091             // Create the editor HTML
     2085            } catch (error) {
     2086                console.error('Error parsing branded keywords:', error);
     2087            }
     2088           
     2089            // Create editor HTML
    20922090            const editorHtml = this.createKeywordEditorHtml(keywordsData, currentKeywords, orderId);
    20932091           
    2094             // Replace the cell content with the editor
     2092            // Replace loading indicator with editor
    20952093            cell.innerHTML = editorHtml;
    20962094           
    2097             // Don't show the save button initially - it will appear when changes are made
     2095            // Replace "Branded KWs" text with the label that includes keywords in parentheses
     2096            const brandedOptions = cell.querySelectorAll('option');
     2097            brandedOptions.forEach(option => {
     2098                if (option.textContent === 'Branded KWs') {
     2099                    option.textContent = brandedKeywordsLabel;
     2100                }
     2101            });
     2102           
     2103            // Set up the editor
     2104            const editor = cell.querySelector('.seoaudp-keyword-editor');
     2105            const saveButton = cell.querySelector('.seoaudp-save-keywords');
     2106            const cancelButton = cell.querySelector('.seoaudp-cancel-edit');
    20982107        } catch (error) {
    20992108            console.error('Error showing keyword editor:', error);
     
    23182327    // Method to create the keyword editor HTML
    23192328    createKeywordEditorHtml(keywordsData, currentKeywords, orderId) {
     2329        // Get branded keywords label with parentheses if available
     2330        let brandedKeywordsLabel = 'Branded KWs';
    23202331        try {
    2321             // Convert keywords string to array of objects
    2322             const keywordArray = keywordsData.split('|')
    2323                 .filter(item => item) // Remove empty items
    2324                 .map(item => {
    2325                     const [keyword, volume, traffic] = item.split(':');
    2326                     return {
    2327                         keyword: keyword || '',
    2328                         volume: parseInt(volume) || 0,
    2329                         traffic: parseInt(traffic) || 0
    2330                     };
    2331                 });
    2332 
    2333             // If no keywords after processing, show message
    2334             if (!keywordArray.length) {
    2335                 return '<div class="seoaudp-no-keywords">No keywords found for this URL</div>';
    2336             }
    2337 
    2338             // Create table with data and checkboxes
    2339             return `
    2340                 <div class="seoaudp-keywords-editor" data-order-id="${orderId}">
    2341                     <div class="seoaudp-keywords-editor-header">
    2342                         <h4>Select Keywords</h4>
    2343                         <button type="button" class="seoaudp-close-keyword-editor">
    2344                             <span class="dashicons dashicons-no-alt"></span>
    2345                         </button>
    2346                     </div>
    2347                     <table class="seoaudp-keywords-table">
    2348                         <thead>
    2349                             <tr>
    2350                                 <th>Keyword</th>
    2351                                 <th>Volume</th>
    2352                                 <th>Select</th>
    2353                             </tr>
    2354                         </thead>
    2355                         <tbody>
    2356                             ${keywordArray.map(kw => `
    2357                                 <tr>
    2358                                     <td>${kw.keyword}</td>
    2359                                     <td>${kw.volume}</td>
    2360                                     <td>
    2361                                         <input type="checkbox"
    2362                                                class="seoaudp-keyword-selector"
    2363                                                data-keyword="${kw.keyword}"
    2364                                                data-original-state="${currentKeywords.includes(kw.keyword)}"
    2365                                                ${currentKeywords.includes(kw.keyword) ? 'checked' : ''} />
    2366                                     </td>
    2367                                 </tr>
    2368                             `).join('')}
    2369                         </tbody>
    2370                     </table>
     2332            const storedBrandedKeywords = localStorage.getItem('seoaudp_branded_keywords');
     2333            if (storedBrandedKeywords) {
     2334                const brandedKeywords = JSON.parse(storedBrandedKeywords);
     2335                if (Array.isArray(brandedKeywords) && brandedKeywords.length > 0) {
     2336                    brandedKeywordsLabel = `Branded KWs (${brandedKeywords.join(', ')})`;
     2337                }
     2338            }
     2339        } catch (error) {
     2340            console.error('Error parsing branded keywords:', error);
     2341        }
     2342       
     2343        let html = `
     2344            <div class="seoaudp-keyword-editor-container">
     2345                <select class="seoaudp-keyword-editor" multiple>
     2346                    <option value="Naked URL" ${currentKeywords.includes('Naked URL') ? 'selected' : ''}>Naked URL</option>
     2347                    <option value="Branded KWs" ${currentKeywords.includes('Branded KWs') ? 'selected' : ''}>${brandedKeywordsLabel}</option>
     2348                    <option value="Keyword" ${currentKeywords.includes('Keyword') ? 'selected' : ''}>Keyword</option>
     2349                </select>
     2350            </div>
     2351        `;
     2352       
     2353        // Add checkboxes for individual keywords
     2354        keywordsData.forEach(keyword => {
     2355            html += `
     2356                <div class="seoaudp-keyword-selector-container">
     2357                    <input type="checkbox" class="seoaudp-keyword-selector" data-keyword="${keyword}" data-original-state="${currentKeywords.includes(keyword)}">
     2358                    <span class="seoaudp-keyword-label">${keyword}</span>
    23712359                </div>
    23722360            `;
    2373         } catch (error) {
    2374             console.error('Error creating keyword editor:', error);
    2375             return '<div class="seoaudp-no-keywords">Error creating keyword editor</div>';
    2376         }
     2361        });
     2362       
     2363        return html;
    23772364    }
    23782365
     
    26292616    // Helper method to set domain-based keywords
    26302617    useDomainKeywords() {
    2631         // Generar keywords basadas en el dominio
    26322618        const domainKeywords = this.getDomainBrandedKeywords();
    2633         console.log("Generated domain keywords:", domainKeywords);
    26342619       
    26352620        if (domainKeywords.length > 0 && this.tomSelect) {
    2636             // Limpiar cualquier keyword existente
     2621            // Clear any existing keywords
    26372622            this.tomSelect.clear();
    26382623           
    2639             // Agregar las nuevas keywords basadas en el dominio
     2624            // Add new keywords based on domain
    26402625            domainKeywords.forEach(keyword => {
    26412626                this.tomSelect.addOption({value: keyword, text: keyword});
     
    26432628            });
    26442629           
    2645             // Habilitar el botón de guardar
     2630            // Enable save button
    26462631            const saveBtn = document.getElementById('save-branded-keywords-btn');
    26472632            if (saveBtn) {
     
    26492634            }
    26502635           
    2651             // Guardar automáticamente las keywords basadas en dominio
     2636            // Automatically save domain-based keywords
    26522637            this.saveBrandedKeywords();
    2653            
    2654             console.log("Domain-based keywords set and saved");
    26552638        } else {
    26562639            console.warn("No domain keywords generated or TomSelect not initialized");
  • seo-ai-audit-tool/tags/1.0.9/changelog.txt

    r3253527 r3257427  
     1= 1.0.9 2025-03-17
     2
     3Improved: Added branded keywords to backlinks order CSV export
     4Updated: Footer GUI update
     5Fixed: Security improvements
     6
    17= 1.0.8 2025-03-10
    28
  • seo-ai-audit-tool/tags/1.0.9/includes/class-seo-audit-data-import.php

    r3250723 r3257427  
    582582        }
    583583
    584         // Rest of the existing code...
    585584        $content = mb_convert_encoding($content, 'UTF-8', mb_detect_encoding($content, 'UTF-8, ISO-8859-1', true));
    586585
     
    588587        $bom = pack('H*','EFBBBF');
    589588        $content = preg_replace("/^$bom/", '', $content);
    590 
    591         // Continue with existing CSV processing...
    592589
    593590        $csv_data = array_map('str_getcsv', explode("\n", $content));
  • seo-ai-audit-tool/tags/1.0.9/includes/class-seo-audit-db.php

    r3250723 r3257427  
    11731173
    11741174    public function seoaudp_handle_ahrefs_backlinks_csv_upload() {
    1175         // ... existing validation code ...
    11761175
    11771176        // Define column mappings
  • seo-ai-audit-tool/tags/1.0.9/includes/views/partials/footer-partial.php

    r3216569 r3257427  
    4040                    <img src="<?php echo esc_url(SEOAUDP_PLUGIN_URL . 'assets/images/stb-logo.png'); ?>" alt="Smart Table Builder" title="Smart Table Builder">
    4141                </a>
    42                 <a href="#" target="_blank" class="seoaudp-footer-plugin-logos">
    43                     <img src="<?php echo esc_url(SEOAUDP_PLUGIN_URL . 'assets/images/hdh-logo.png'); ?>" alt="Help Desk Hero" title="Help Desk Hero">
     42                <a href="https://seo-ai-audit-tool.designful.ca/" target="_blank" class="seoaudp-footer-plugin-logos">
     43                    <img src="<?php echo esc_url(SEOAUDP_PLUGIN_URL . 'assets/images/saat-logo.png'); ?>" alt="SEO Audit Tool" title="SEO Audit Tool">
    4444                </a>
    4545            </div>
  • seo-ai-audit-tool/tags/1.0.9/readme.md

    r3253527 r3257427  
    22Contributors: Designful
    33Plugin URL: https://seo-ai-audit-tool.designful.ca/
    4 Version: 1.0.8
     4Version: 1.0.9
    55Tags: seo audit, ai seo, conversion optimization, content analysis, search intent
    66Requires at least: 4.0
    77Tested up to: 6.7
    8 Stable tag: 1.0.8
     8Stable tag: 1.0.9
    99Requires PHP: 7.4
    1010License: GPLv2 or later
  • seo-ai-audit-tool/tags/1.0.9/seo-ai-audit-tool.php

    r3253527 r3257427  
    44 * Plugin URI: https://designful.ca/apps/seo-ai-audit-tool/
    55 * Description: A WordPress plugin to audit SEO elements of pages and perform AI-powered content analysis
    6  * Version:     1.0.8
     6 * Version:     1.0.9
    77 * Author:      Designful
    88 * License:     GPL2
     
    2020define('SEOAUDP_PLUGIN_DIR', plugin_dir_path(__FILE__));
    2121define('SEOAUDP_PLUGIN_URL', plugin_dir_url(__FILE__));
    22 define('SEOAUDP_PLUGIN_VERSION', '1.0.8');
     22define('SEOAUDP_PLUGIN_VERSION', '1.0.9');
    2323define('SEOAUDP_PLUGIN_BETA_VERSION', false);
    2424define('SEOAUDP_DB_VERSION', '1.6');
     
    434434    seoaudp_debug_log($_POST);
    435435   
    436     try {
    437         // ... existing code ...
    438     } catch (Exception $e) {
    439         seoaudp_debug_log('Error: ' . $e->getMessage());
    440         // ... existing error handling ...
    441     }
    442 }
     436}
  • seo-ai-audit-tool/trunk/assets/js/seoaudp-backlinks-analyzer.js

    r3252394 r3257427  
    16861686        }
    16871687
     1688        // Get branded keywords for display
     1689        let brandedKeywords = [];
     1690        try {
     1691            const storedBrandedKeywords = localStorage.getItem('seoaudp_branded_keywords');
     1692            if (storedBrandedKeywords) {
     1693                brandedKeywords = JSON.parse(storedBrandedKeywords);
     1694            }
     1695        } catch (error) {
     1696            console.error('Error parsing branded keywords:', error);
     1697        }
     1698       
     1699        // Branded keywords label
     1700        const brandedKeywordsLabel = Array.isArray(brandedKeywords) && brandedKeywords.length > 0
     1701            ? `Branded KWs (${brandedKeywords.join(', ')})`
     1702            : 'Branded KWs';
     1703
    16881704        // First, ensure all orders have page IDs
    16891705        const ordersWithPageIds = orders.map(async order => {
     
    17601776                    const brandedKwLinks = brandedKwKeyword ? (brandedKwKeyword.desiredLinks || 1) : '';
    17611777                   
     1778                    // Get the current branded keywords from localStorage
     1779                    let brandedKeywordsLabel = 'Branded KWs';
     1780                    try {
     1781                        const storedBrandedKeywords = localStorage.getItem('seoaudp_branded_keywords');
     1782                        if (storedBrandedKeywords) {
     1783                            const brandedKeywords = JSON.parse(storedBrandedKeywords);
     1784                            if (Array.isArray(brandedKeywords) && brandedKeywords.length > 0) {
     1785                                brandedKeywordsLabel = `Branded KWs (${brandedKeywords.join(', ')})`;
     1786                            }
     1787                        }
     1788                    } catch (error) {
     1789                        console.error('Error parsing branded keywords:', error);
     1790                    }
     1791                   
    17621792                    // Add first row with URL, Naked URL keyword and delete button (with top border for group)
    17631793                    html += `
     
    17821812                                <td></td>
    17831813                                <td></td>
    1784                                 <td class="seoaudp-keyword-cell">Branded KWs</td>
     1814                                <td class="seoaudp-keyword-cell">${brandedKeywordsLabel}</td>
    17851815                                <td>${brandedKwLinks}</td>
    17861816                                <td class="seoaudp-order-actions">
     
    20262056    // Update the showKeywordEditor method to handle multiple keywords
    20272057    async showKeywordEditor(cell, orderId, pageUrl) {
     2058        // First create a loading indicator
     2059        cell.innerHTML = `<span class="seoaudp-loading-spinner">Loading...</span>`;
     2060       
    20282061        try {
    2029             // Store the original content
    2030             const originalContent = cell.innerHTML;
    2031             cell.setAttribute('data-original-content', originalContent);
    2032            
    2033             // Get the row
    2034             const row = cell.closest('tr');
    2035            
    2036             // Try to get page ID directly from the row
    2037             let pageId = row.getAttribute('data-page-id');
    2038            
    2039             // If not found, try to get it from the hidden input
     2062            // Get page ID from URL
     2063            let pageId = await this.getPageIdFromUrl(pageUrl);
     2064           
    20402065            if (!pageId) {
    2041                 const hiddenInput = row.querySelector('.seoaudp-page-id-hidden');
    2042                 if (hiddenInput) {
    2043                     pageId = hiddenInput.value;
    2044                 }
    2045             }
    2046            
    2047             // If still not found, try to get it from the URL
    2048             if (!pageId) {
    2049                 // Make sure we have a valid URL
    2050                 if (!pageUrl) {
    2051                     const anchor = row.querySelector('a');
    2052                     if (anchor) {
    2053                         pageUrl = anchor.href;
    2054                     } else {
    2055                         // Try to get URL from data attribute
    2056                         pageUrl = row.getAttribute('data-page-url');
    2057                         if (!pageUrl) {
    2058                             // Try to get URL from a sibling row that has an anchor
    2059                             const siblingWithAnchor = row.parentElement.querySelector('tr[data-page-url] a');
    2060                             if (siblingWithAnchor) {
    2061                                 pageUrl = siblingWithAnchor.href;
    2062                             } else {
    2063                                 console.error('Could not determine page URL');
    2064                                 alert('Could not determine page URL for this row');
    2065                                 return;
    2066                             }
    2067                         }
     2066                throw new Error('Could not determine page ID');
     2067            }
     2068           
     2069            // Get all keywords for this page
     2070            const keywordsData = await this.getKeywordsForPage(pageId);
     2071           
     2072            // Get current keywords in the row
     2073            const currentKeywords = this.getCurrentKeywords(cell);
     2074           
     2075            // Get branded keywords label with parentheses if available
     2076            let brandedKeywordsLabel = 'Branded KWs';
     2077            try {
     2078                const storedBrandedKeywords = localStorage.getItem('seoaudp_branded_keywords');
     2079                if (storedBrandedKeywords) {
     2080                    const brandedKeywords = JSON.parse(storedBrandedKeywords);
     2081                    if (Array.isArray(brandedKeywords) && brandedKeywords.length > 0) {
     2082                        brandedKeywordsLabel = `Branded KWs (${brandedKeywords.join(', ')})`;
    20682083                    }
    20692084                }
    2070                
    2071                 // Get page ID from URL
    2072                 pageId = await this.getPageIdFromUrl(pageUrl);
    2073             }
    2074            
    2075             if (!pageId) {
    2076                 console.error('Could not determine page ID');
    2077                 alert('Could not determine page ID for this row');
    2078                 return;
    2079             }
    2080            
    2081             // Get keywords for this page
    2082             const keywordsData = await this.getKeywordsForPage(pageId);
    2083             if (!keywordsData) {
    2084                 alert('No keywords found for this page');
    2085                 return;
    2086             }
    2087            
    2088             // Get all currently selected keywords for this order
    2089             const currentKeywords = this.getCurrentKeywords(cell);
    2090            
    2091             // Create the editor HTML
     2085            } catch (error) {
     2086                console.error('Error parsing branded keywords:', error);
     2087            }
     2088           
     2089            // Create editor HTML
    20922090            const editorHtml = this.createKeywordEditorHtml(keywordsData, currentKeywords, orderId);
    20932091           
    2094             // Replace the cell content with the editor
     2092            // Replace loading indicator with editor
    20952093            cell.innerHTML = editorHtml;
    20962094           
    2097             // Don't show the save button initially - it will appear when changes are made
     2095            // Replace "Branded KWs" text with the label that includes keywords in parentheses
     2096            const brandedOptions = cell.querySelectorAll('option');
     2097            brandedOptions.forEach(option => {
     2098                if (option.textContent === 'Branded KWs') {
     2099                    option.textContent = brandedKeywordsLabel;
     2100                }
     2101            });
     2102           
     2103            // Set up the editor
     2104            const editor = cell.querySelector('.seoaudp-keyword-editor');
     2105            const saveButton = cell.querySelector('.seoaudp-save-keywords');
     2106            const cancelButton = cell.querySelector('.seoaudp-cancel-edit');
    20982107        } catch (error) {
    20992108            console.error('Error showing keyword editor:', error);
     
    23182327    // Method to create the keyword editor HTML
    23192328    createKeywordEditorHtml(keywordsData, currentKeywords, orderId) {
     2329        // Get branded keywords label with parentheses if available
     2330        let brandedKeywordsLabel = 'Branded KWs';
    23202331        try {
    2321             // Convert keywords string to array of objects
    2322             const keywordArray = keywordsData.split('|')
    2323                 .filter(item => item) // Remove empty items
    2324                 .map(item => {
    2325                     const [keyword, volume, traffic] = item.split(':');
    2326                     return {
    2327                         keyword: keyword || '',
    2328                         volume: parseInt(volume) || 0,
    2329                         traffic: parseInt(traffic) || 0
    2330                     };
    2331                 });
    2332 
    2333             // If no keywords after processing, show message
    2334             if (!keywordArray.length) {
    2335                 return '<div class="seoaudp-no-keywords">No keywords found for this URL</div>';
    2336             }
    2337 
    2338             // Create table with data and checkboxes
    2339             return `
    2340                 <div class="seoaudp-keywords-editor" data-order-id="${orderId}">
    2341                     <div class="seoaudp-keywords-editor-header">
    2342                         <h4>Select Keywords</h4>
    2343                         <button type="button" class="seoaudp-close-keyword-editor">
    2344                             <span class="dashicons dashicons-no-alt"></span>
    2345                         </button>
    2346                     </div>
    2347                     <table class="seoaudp-keywords-table">
    2348                         <thead>
    2349                             <tr>
    2350                                 <th>Keyword</th>
    2351                                 <th>Volume</th>
    2352                                 <th>Select</th>
    2353                             </tr>
    2354                         </thead>
    2355                         <tbody>
    2356                             ${keywordArray.map(kw => `
    2357                                 <tr>
    2358                                     <td>${kw.keyword}</td>
    2359                                     <td>${kw.volume}</td>
    2360                                     <td>
    2361                                         <input type="checkbox"
    2362                                                class="seoaudp-keyword-selector"
    2363                                                data-keyword="${kw.keyword}"
    2364                                                data-original-state="${currentKeywords.includes(kw.keyword)}"
    2365                                                ${currentKeywords.includes(kw.keyword) ? 'checked' : ''} />
    2366                                     </td>
    2367                                 </tr>
    2368                             `).join('')}
    2369                         </tbody>
    2370                     </table>
     2332            const storedBrandedKeywords = localStorage.getItem('seoaudp_branded_keywords');
     2333            if (storedBrandedKeywords) {
     2334                const brandedKeywords = JSON.parse(storedBrandedKeywords);
     2335                if (Array.isArray(brandedKeywords) && brandedKeywords.length > 0) {
     2336                    brandedKeywordsLabel = `Branded KWs (${brandedKeywords.join(', ')})`;
     2337                }
     2338            }
     2339        } catch (error) {
     2340            console.error('Error parsing branded keywords:', error);
     2341        }
     2342       
     2343        let html = `
     2344            <div class="seoaudp-keyword-editor-container">
     2345                <select class="seoaudp-keyword-editor" multiple>
     2346                    <option value="Naked URL" ${currentKeywords.includes('Naked URL') ? 'selected' : ''}>Naked URL</option>
     2347                    <option value="Branded KWs" ${currentKeywords.includes('Branded KWs') ? 'selected' : ''}>${brandedKeywordsLabel}</option>
     2348                    <option value="Keyword" ${currentKeywords.includes('Keyword') ? 'selected' : ''}>Keyword</option>
     2349                </select>
     2350            </div>
     2351        `;
     2352       
     2353        // Add checkboxes for individual keywords
     2354        keywordsData.forEach(keyword => {
     2355            html += `
     2356                <div class="seoaudp-keyword-selector-container">
     2357                    <input type="checkbox" class="seoaudp-keyword-selector" data-keyword="${keyword}" data-original-state="${currentKeywords.includes(keyword)}">
     2358                    <span class="seoaudp-keyword-label">${keyword}</span>
    23712359                </div>
    23722360            `;
    2373         } catch (error) {
    2374             console.error('Error creating keyword editor:', error);
    2375             return '<div class="seoaudp-no-keywords">Error creating keyword editor</div>';
    2376         }
     2361        });
     2362       
     2363        return html;
    23772364    }
    23782365
     
    26292616    // Helper method to set domain-based keywords
    26302617    useDomainKeywords() {
    2631         // Generar keywords basadas en el dominio
    26322618        const domainKeywords = this.getDomainBrandedKeywords();
    2633         console.log("Generated domain keywords:", domainKeywords);
    26342619       
    26352620        if (domainKeywords.length > 0 && this.tomSelect) {
    2636             // Limpiar cualquier keyword existente
     2621            // Clear any existing keywords
    26372622            this.tomSelect.clear();
    26382623           
    2639             // Agregar las nuevas keywords basadas en el dominio
     2624            // Add new keywords based on domain
    26402625            domainKeywords.forEach(keyword => {
    26412626                this.tomSelect.addOption({value: keyword, text: keyword});
     
    26432628            });
    26442629           
    2645             // Habilitar el botón de guardar
     2630            // Enable save button
    26462631            const saveBtn = document.getElementById('save-branded-keywords-btn');
    26472632            if (saveBtn) {
     
    26492634            }
    26502635           
    2651             // Guardar automáticamente las keywords basadas en dominio
     2636            // Automatically save domain-based keywords
    26522637            this.saveBrandedKeywords();
    2653            
    2654             console.log("Domain-based keywords set and saved");
    26552638        } else {
    26562639            console.warn("No domain keywords generated or TomSelect not initialized");
  • seo-ai-audit-tool/trunk/changelog.txt

    r3253527 r3257427  
     1= 1.0.9 2025-03-17
     2
     3Improved: Added branded keywords to backlinks order CSV export
     4Updated: Footer GUI update
     5Fixed: Security improvements
     6
    17= 1.0.8 2025-03-10
    28
  • seo-ai-audit-tool/trunk/includes/class-seo-audit-data-import.php

    r3250723 r3257427  
    582582        }
    583583
    584         // Rest of the existing code...
    585584        $content = mb_convert_encoding($content, 'UTF-8', mb_detect_encoding($content, 'UTF-8, ISO-8859-1', true));
    586585
     
    588587        $bom = pack('H*','EFBBBF');
    589588        $content = preg_replace("/^$bom/", '', $content);
    590 
    591         // Continue with existing CSV processing...
    592589
    593590        $csv_data = array_map('str_getcsv', explode("\n", $content));
  • seo-ai-audit-tool/trunk/includes/class-seo-audit-db.php

    r3250723 r3257427  
    11731173
    11741174    public function seoaudp_handle_ahrefs_backlinks_csv_upload() {
    1175         // ... existing validation code ...
    11761175
    11771176        // Define column mappings
  • seo-ai-audit-tool/trunk/includes/views/partials/footer-partial.php

    r3216569 r3257427  
    4040                    <img src="<?php echo esc_url(SEOAUDP_PLUGIN_URL . 'assets/images/stb-logo.png'); ?>" alt="Smart Table Builder" title="Smart Table Builder">
    4141                </a>
    42                 <a href="#" target="_blank" class="seoaudp-footer-plugin-logos">
    43                     <img src="<?php echo esc_url(SEOAUDP_PLUGIN_URL . 'assets/images/hdh-logo.png'); ?>" alt="Help Desk Hero" title="Help Desk Hero">
     42                <a href="https://seo-ai-audit-tool.designful.ca/" target="_blank" class="seoaudp-footer-plugin-logos">
     43                    <img src="<?php echo esc_url(SEOAUDP_PLUGIN_URL . 'assets/images/saat-logo.png'); ?>" alt="SEO Audit Tool" title="SEO Audit Tool">
    4444                </a>
    4545            </div>
  • seo-ai-audit-tool/trunk/readme.md

    r3253527 r3257427  
    22Contributors: Designful
    33Plugin URL: https://seo-ai-audit-tool.designful.ca/
    4 Version: 1.0.8
     4Version: 1.0.9
    55Tags: seo audit, ai seo, conversion optimization, content analysis, search intent
    66Requires at least: 4.0
    77Tested up to: 6.7
    8 Stable tag: 1.0.8
     8Stable tag: 1.0.9
    99Requires PHP: 7.4
    1010License: GPLv2 or later
  • seo-ai-audit-tool/trunk/seo-ai-audit-tool.php

    r3253527 r3257427  
    44 * Plugin URI: https://designful.ca/apps/seo-ai-audit-tool/
    55 * Description: A WordPress plugin to audit SEO elements of pages and perform AI-powered content analysis
    6  * Version:     1.0.8
     6 * Version:     1.0.9
    77 * Author:      Designful
    88 * License:     GPL2
     
    2020define('SEOAUDP_PLUGIN_DIR', plugin_dir_path(__FILE__));
    2121define('SEOAUDP_PLUGIN_URL', plugin_dir_url(__FILE__));
    22 define('SEOAUDP_PLUGIN_VERSION', '1.0.8');
     22define('SEOAUDP_PLUGIN_VERSION', '1.0.9');
    2323define('SEOAUDP_PLUGIN_BETA_VERSION', false);
    2424define('SEOAUDP_DB_VERSION', '1.6');
     
    434434    seoaudp_debug_log($_POST);
    435435   
    436     try {
    437         // ... existing code ...
    438     } catch (Exception $e) {
    439         seoaudp_debug_log('Error: ' . $e->getMessage());
    440         // ... existing error handling ...
    441     }
    442 }
     436}
Note: See TracChangeset for help on using the changeset viewer.