| Server IP : 38.190.208.107 / Your IP : 216.73.217.105 Web Server : nginx/1.28.1 System : Linux ht2026040333114 6.1.0-10-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.37-1 (2023-07-03) x86_64 User : root ( 0) PHP Version : 8.2.28 Disable Function : passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv,eval,assert,passthru,system,exec,shell_exec,popen,proc_open MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /www/wwwroot/wp.10/wp-content/plugins/clarity-seo/includes/ |
Upload File : |
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
// Add SEO Audit page under Tools
function clarity_seo_add_audit_page() {
add_management_page(
esc_html__( 'SEO Audit', 'clarity-seo' ),
esc_html__( 'SEO Audit', 'clarity-seo' ),
'manage_options',
'clarity-seo-audit',
'clarity_seo_audit_callback'
);
}
add_action('admin_menu', 'clarity_seo_add_audit_page');
// Audit callback - 30-point dynamic check
function clarity_seo_audit_callback() {
$audit_results = [];
$recent_posts = get_posts(['numberposts' => 10, 'post_status' => 'publish']);
$home_url = home_url();
$admin_url = admin_url();
// 1. HTTPS Enabled
$is_https = is_ssl();
$status = $is_https ? 'Pass' : 'Fail - Enable SSL for security and SEO.';
$audit_results[] = [
'name' => 'HTTPS Enabled',
'description' => 'Checks if your site uses HTTPS.',
'status' => $status,
'action' => $is_https ? '' : '<a href="https://wordpress.org/documentation/article/https-for-wordpress/" target="_blank" class="button">Learn How to Fix</a>'
];
// 2. Permalink Structure
$has_permalinks = get_option('permalink_structure');
$status = $has_permalinks ? 'Pass' : 'Fail - Use pretty permalinks like /%postname%/.';
$audit_results[] = [
'name' => 'Permalink Structure',
'description' => 'Ensures user-friendly URL structures.',
'status' => $status,
'action' => '<a href="' . $admin_url . 'options-permalink.php" class="button">' . ($has_permalinks ? 'Check' : 'Fix') . '</a>'
];
// 3. XML Sitemap Exists
$sitemap_body = wp_remote_retrieve_body(wp_remote_get($home_url . '/sitemap.xml'));
$status = $sitemap_body ? 'Pass' : 'Fail - Generate sitemap.';
$audit_results[] = [
'name' => 'XML Sitemap',
'description' => 'Verifies if sitemap.xml is accessible.',
'status' => $status,
'action' => '<a href="' . $home_url . '/sitemap.xml" target="_blank" class="button">View Sitemap</a>'
];
// 4. Robots.txt Exists
$robots_body = wp_remote_retrieve_body(wp_remote_get($home_url . '/robots.txt'));
$status = $robots_body ? 'Pass' : 'Fail - Create robots.txt.';
$audit_results[] = [
'name' => 'Robots.txt Exists',
'description' => 'Checks for robots.txt file.',
'status' => $status,
'action' => '<a href="' . $home_url . '/robots.txt" target="_blank" class="button">View Robots.txt</a>'
];
// 5. Alt Tags on Images (scan recent posts)
$has_alt = true;
$failing_posts = [];
foreach ($recent_posts as $p) {
if (preg_match_all('/<img [^>]*>/', $p->post_content, $imgs)) {
foreach ($imgs[0] as $img) {
if (strpos($img, 'alt=') === false || strpos($img, 'alt=""') !== false) {
$has_alt = false;
$failing_posts[] = $p->post_title . ' (ID: ' . $p->ID . ')';
}
}
}
}
$status = $has_alt ? 'Pass' : 'Fail - Missing alt tags in posts: ' . implode(', ', $failing_posts);
$audit_results[] = [
'name' => 'Image Alt Tags',
'description' => 'Ensures images have alt attributes in recent posts.',
'status' => $status,
'action' => $has_alt ? '' : '<a href="' . $admin_url . 'upload.php" class="button">Fix Images</a>'
];
// 6. Meta Titles Set
$titles_set = 0;
foreach ($recent_posts as $p) {
if (get_post_meta($p->ID, '_clarity_seo_meta_title', true)) $titles_set++;
}
$status = $titles_set > 5 ? 'Pass' : 'Fail - Set meta titles for more posts.';
$audit_results[] = [
'name' => 'Meta Titles',
'description' => 'Checks if recent posts have custom meta titles.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="' . $admin_url . 'edit.php" class="button">Edit Posts</a>'
];
// 7. Meta Descriptions Set
$descs_set = 0;
foreach ($recent_posts as $p) {
if (get_post_meta($p->ID, '_clarity_seo_meta_description', true)) $descs_set++;
}
$status = $descs_set > 5 ? 'Pass' : 'Fail - Set meta descriptions for more posts.';
$audit_results[] = [
'name' => 'Meta Descriptions',
'description' => 'Checks if recent posts have custom meta descriptions.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="' . $admin_url . 'edit.php" class="button">Edit Posts</a>'
];
// 8. Canonical Tags
$has_canonical = true;
foreach ($recent_posts as $p) {
if (empty(rel_canonical())) $has_canonical = false; // Simplified check
}
$status = $has_canonical ? 'Pass' : 'Fail - Add canonical tags.';
$audit_results[] = [
'name' => 'Canonical Tags',
'description' => 'Ensures canonical URLs are set.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="https://developer.wordpress.org/reference/functions/rel_canonical/" target="_blank" class="button">Learn More</a>'
];
// 9. Mobile Friendly
// Use Google API or simple check; for simplicity, assume pass if responsive theme
$theme = wp_get_theme();
$is_mobile_friendly = strpos($theme->get('Description'), 'responsive') !== false;
$status = $is_mobile_friendly ? 'Pass' : 'Fail - Use a mobile-friendly theme.';
$audit_results[] = [
'name' => 'Mobile Friendly',
'description' => 'Checks if theme is responsive.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="' . $admin_url . 'themes.php" class="button">Change Theme</a>'
];
// 10. Page Speed (simple check, real would use API)
$status = 'Warning - Test with Google PageSpeed.';
$audit_results[] = [
'name' => 'Page Speed',
'description' => 'Reminder to check site speed.',
'status' => $status,
'action' => '<a href="https://pagespeed.web.dev/" target="_blank" class="button">Test Now</a>'
];
// 11. Broken Links (scan recent posts)
$has_broken_links = false;
foreach ($recent_posts as $p) {
if (preg_match_all('/<a href="(.*?)"/', $p->post_content, $links)) {
foreach ($links[1] as $link) {
$response = wp_remote_head($link);
if (wp_remote_retrieve_response_code($response) >= 400) $has_broken_links = true;
}
}
}
$status = !$has_broken_links ? 'Pass' : 'Fail - Fix broken links.';
$audit_results[] = [
'name' => 'Broken Links',
'description' => 'Scans for 404 links in recent posts.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="https://wordpress.org/plugins/broken-link-checker/" target="_blank" class="button">Install Checker</a>'
];
// 12. Duplicate Content
$duplicate = false;
// Simplified: Check if multiple posts have same title
$titles = array_map(function($p) { return $p->post_title; }, $recent_posts);
if (count($titles) !== count(array_unique($titles))) $duplicate = true;
$status = !$duplicate ? 'Pass' : 'Fail - Avoid duplicate titles.';
$audit_results[] = [
'name' => 'Duplicate Content',
'description' => 'Checks for duplicate titles in recent posts.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="' . $admin_url . 'edit.php" class="button">Edit Posts</a>'
];
// 13. H1 Tags
$has_h1 = true;
foreach ($recent_posts as $p) {
if (substr_count($p->post_content, '<h1') < 1) $has_h1 = false;
}
$status = $has_h1 ? 'Pass' : 'Fail - Add H1 tags to posts.';
$audit_results[] = [
'name' => 'H1 Tags',
'description' => 'Ensures posts have at least one H1.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="' . $admin_url . 'edit.php" class="button">Edit Posts</a>'
];
// 14. Keyword Density (simplified)
$has_density = true;
foreach ($recent_posts as $p) {
$focus = get_post_meta($p->ID, '_clarity_seo_focus_keywords', true);
if ($focus) {
$content = wp_strip_all_tags($p->post_content);
$words = str_word_count($content);
$density = (substr_count(strtolower($content), strtolower($focus)) / $words) * 100;
if ($density < 0.5) $has_density = false;
}
}
$status = $has_density ? 'Pass' : 'Fail - Optimize keyword density.';
$audit_results[] = [
'name' => 'Keyword Density',
'description' => 'Checks focus keyword usage in content.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="' . $admin_url . 'edit.php" class="button">Edit Posts</a>'
];
// 15. Internal Links
$has_internal = true;
foreach ($recent_posts as $p) {
if (substr_count($p->post_content, home_url()) < 1) $has_internal = false;
}
$status = $has_internal ? 'Pass' : 'Fail - Add internal links.';
$audit_results[] = [
'name' => 'Internal Links',
'description' => 'Ensures posts have internal links.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="' . $admin_url . 'edit.php" class="button">Edit Posts</a>'
];
// 16. External Links
$has_external = true;
foreach ($recent_posts as $p) {
if (preg_match('/<a href="(http[s]?://(?!' . preg_quote(wp_parse_url(home_url(), PHP_URL_HOST)) . '))/', $p->post_content) < 1) $has_external = false;
}
$status = $has_external ? 'Pass' : 'Warning - Consider adding external links.';
$audit_results[] = [
'name' => 'External Links',
'description' => 'Checks for external links in posts.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="' . $admin_url . 'edit.php" class="button">Edit Posts</a>'
];
// 17. Readability Score
$good_readability = true;
foreach ($recent_posts as $p) {
$content = wp_strip_all_tags($p->post_content);
$words = str_word_count($content);
$sentences = preg_match_all('/[.!?]+/', $content) ?: 1;
preg_match_all('/[aeiouy]+/i', $content, $syllable_matches);
$syllables = count($syllable_matches[0]);
if ($words > 0 && $syllables > 0) {
$asl = $words / $sentences;
$asw = $syllables / $words;
$score = 206.835 - (1.015 * $asl) - (84.6 * $asw);
if ($score < 60) $good_readability = false;
}
}
$status = $good_readability ? 'Pass' : 'Fail - Improve readability.';
$audit_results[] = [
'name' => 'Readability',
'description' => 'Flesch-Kincaid score above 60.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="' . $admin_url . 'edit.php" class="button">Edit Posts</a>'
];
// 18. GSC Connected
$gsc_key = get_option('clarity_seo_gsc_key', '');
$status = !empty($gsc_key) ? 'Pass' : 'Fail - Connect GSC.';
$audit_results[] = [
'name' => 'GSC Connected',
'description' => 'Checks if GSC API is set.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="' . $admin_url . 'options-general.php?page=clarity-seo" class="button">Set in Settings</a>'
];
// 19. Social Links Set
$social = get_option('clarity_seo_social_links', '');
$status = !empty($social) ? 'Pass' : 'Fail - Add social profiles.';
$audit_results[] = [
'name' => 'Social Links',
'description' => 'Ensures social links are configured.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="' . $admin_url . 'options-general.php?page=clarity-seo" class="button">Fix in Settings</a>'
];
// 20. Logo Set
$logo = get_option('clarity_seo_logo_url', '');
$status = !empty($logo) ? 'Pass' : 'Fail - Upload logo.';
$audit_results[] = [
'name' => 'Organization Logo',
'description' => 'Checks if logo URL is set for schema.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="' . $admin_url . 'options-general.php?page=clarity-seo" class="button">Fix in Settings</a>'
];
// 21. Contact Point
$contact = get_option('clarity_seo_contact_phone', '');
$status = !empty($contact) ? 'Pass' : 'Fail - Add contact info.';
$audit_results[] = [
'name' => 'Contact Point',
'description' => 'Ensures contact phone is set for schema.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="' . $admin_url . 'options-general.php?page=clarity-seo" class="button">Fix in Settings</a>'
];
// 22. Schemas Implemented
$schema_set = 0;
foreach ($recent_posts as $p) {
if (get_post_meta($p->ID, '_clarity_seo_type', true)) $schema_set++;
}
$status = $schema_set > 5 ? 'Pass' : 'Fail - Add schemas to more posts.';
$audit_results[] = [
'name' => 'Schemas Implemented',
'description' => 'Checks schema usage in recent posts.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="' . $admin_url . 'edit.php" class="button">Edit Posts</a>'
];
// 23. Auto Image Alt Enabled
$auto_alt = get_option('clarity_seo_auto_image_alt', 'off');
$status = $auto_alt === 'on' ? 'Pass' : 'Fail - Enable in settings for better image SEO.';
$audit_results[] = [
'name' => 'Auto Image Alt Enabled',
'description' => 'Checks if auto image alt generation is on.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="' . $admin_url . 'options-general.php?page=clarity-seo" class="button">Fix in Settings</a>'
];
// 24. Local SEO Configured
$local_address = get_option('clarity_seo_local_address', '');
$status = !empty($local_address) ? 'Pass' : 'Fail - Set business address in settings.';
$audit_results[] = [
'name' => 'Local SEO Configured',
'description' => 'Ensures local business details are set.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="' . $admin_url . 'options-general.php?page=clarity-seo" class="button">Fix in Settings</a>'
];
// 25. Breadcrumbs Enabled
$breadcrumbs = function_exists('clarity_seo_breadcrumbs_shortcode');
$status = $breadcrumbs ? 'Pass' : 'Fail - Enable breadcrumbs.';
$audit_results[] = [
'name' => 'Breadcrumbs',
'description' => 'Checks if breadcrumbs are implemented.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="' . $admin_url . 'options-general.php?page=clarity-seo" class="button">Fix</a>'
];
// 26. Redirects Set
$redirects = get_option('clarity_seo_redirects', []);
$status = !empty($redirects) ? 'Pass' : 'Warning - Set up redirects if needed.';
$audit_results[] = [
'name' => 'Redirects',
'description' => 'Checks if any redirects are configured.',
'status' => $status,
'action' => '<a href="' . $admin_url . 'options-general.php?page=clarity-seo" class="button">Manage Redirects</a>'
];
// 27. 404 Logs
$logs = get_option('clarity_seo_404_logs', []);
$status = empty($logs) ? 'Pass - No recent 404s' : 'Warning - Review 404 logs.';
$audit_results[] = [
'name' => '404 Errors',
'description' => 'Checks for recent 404 logs.',
'status' => $status,
'action' => '<a href="' . $admin_url . 'tools.php?page=clarity-seo-404" class="button">View Logs</a>'
];
// 28. Keyword Tracking
$keywords = get_option('clarity_seo_tracked_keywords', []);
$status = !empty($keywords) ? 'Pass' : 'Fail - Add keywords to track.';
$audit_results[] = [
'name' => 'Keyword Tracking',
'description' => 'Ensures keywords are set for tracking.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="' . $admin_url . 'options-general.php?page=clarity-seo" class="button">Set Keywords</a>'
];
// 29. OG Image Default
$og_image = get_option('clarity_seo_default_og_image', '');
$status = !empty($og_image) ? 'Pass' : 'Fail - Set default OG image.';
$audit_results[] = [
'name' => 'Default OG Image',
'description' => 'Checks if default Open Graph image is set.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="' . $admin_url . 'options-general.php?page=clarity-seo" class="button">Fix in Settings</a>'
];
// 30. Wizard Completed
$wizard = get_option('clarity_seo_wizard_completed', false);
$status = $wizard ? 'Pass' : 'Fail - Complete setup wizard.';
$audit_results[] = [
'name' => 'Setup Wizard',
'description' => 'Ensures initial setup is done.',
'status' => $status,
'action' => $status === 'Pass' ? '' : '<a href="' . $admin_url . 'options-general.php?page=clarity-seo-wizard" class="button">Run Wizard</a>'
];
$fail_count = count(array_filter($audit_results, function($r) { return strpos($r['status'], 'Fail') !== false; }));
?>
<div class="wrap">
<h1><?php esc_html_e('SEO Audit Checklist', 'clarity-seo'); ?></h1>
<p><?php esc_html_e('Running 30 dynamic SEO tests on your site...', 'clarity-seo'); ?></p>
<table class="wp-list-table widefat fixed striped" style="border: 1px solid #ddd;">
<thead><tr><th>Test</th><th>Status</th><th>Action</th></tr></thead>
<tbody>
<?php foreach ($audit_results as $result): ?>
<?php
$status_color = strpos($result['status'], 'Pass') !== false ? 'green' : (strpos($result['status'], 'Fail') !== false ? 'red' : 'orange');
?>
<tr>
<td title="<?php echo esc_attr($result['description']); ?>"><?php echo esc_html($result['name']); ?></td>
<td><strong style="color: <?php echo esc_attr($status_color); ?>;"><?php echo esc_html($result['status']); ?></strong></td>
<td><?php echo wp_kses_post($result['action']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<p><?php echo $fail_count == 0 ? esc_html__('All Pass! Great SEO foundation.', 'clarity-seo') : esc_html__('Fix fails for better SEO.', 'clarity-seo'); ?></p>
</div>
<?php
}
?>