How to Audit an Inherited WordPress Site

Someone hands you a WordPress site. Maybe you are the new agency, maybe the old developer vanished, maybe a colleague left and the site is now, congratulations, yours. Nobody knows the hosting password on the first try. There is a plugin called temp-fix-DO-NOT-DELETE. The About page was last edited years ago by a user named admin2.

Resist the urge to start fixing things. An inherited site is a crime scene until proven otherwise: your first job is to document what exists, not to change it. Every change you make before you have a backup and a map is a change you cannot cleanly undo — and if something was already broken, you will inherit the blame for it the moment you touch anything.

Here is the audit I run, in the order I run it. With WP-CLI access it takes an afternoon; through the admin dashboard alone, budget a day.

Step 0: Take a backup before you breathe on anything

Before the first change — before updating a single plugin — capture the site exactly as you received it:

  • Files: a full copy of the WordPress directory, including wp-config.php and anything odd sitting next to it.
  • Database: wp db export inherited-baseline-$(date +%F).sql, or a phpMyAdmin export if that is what you have.
  • Store it off the server. A backup on the same machine as the site is a snapshot, not a backup.

This baseline is your alibi and your undo button. If a client later asks whether the site was already infected when you took over, you can answer with evidence.

Step 1: Inventory the access you actually have

Sites accumulate accounts the way drawers accumulate cables. Make a list with four columns — service, URL, credential status, who else has access — and fill it in for:

  • WordPress admin (can you log in? do you have a real Administrator account, or someone's shared login?)
  • Hosting control panel and SFTP/SSH
  • Domain registrar (frequently a different company than the host, frequently the thing nobody can find)
  • DNS (sometimes at the registrar, sometimes Cloudflare, sometimes a third place)
  • Email sending — is the site sending via the server's PHP mail, an SMTP plugin, or a service like Postmark or SES with an API key that belongs to someone's personal account?
  • Third-party services wired into the site: analytics, backup services, CDN, payment gateways

The decision rule: anything you cannot log into today is a ticket you open today. Registrar transfers and hosting ownership changes can take days and require the previous owner's cooperation, which has a habit of expiring. Chase these first, in parallel with everything else.

While you are in there, rotate what you can: your own fresh admin account (then demote the shared ones), new SFTP credentials, new database password if the host allows it without drama. And check the users table for surprises: wp user list --role=administrator. Five administrators on a brochure site is a finding, not a fact of life.

Step 2: Establish what is running

Four commands give you the skeleton of the site:

  • wp core version — and compare against the current release. A site two major versions behind tells you about the maintenance culture you are inheriting.
  • wp cli info — confirms the PHP version. Any version not on PHP's supported-versions list is no longer receiving security fixes: it goes on the remediation list, near the top.
  • wp plugin list --fields=name,status,update,version — the full plugin census.
  • wp theme list — active theme, parent theme, and the graveyard of inactive ones.

No WP-CLI? The Site Health screen (Tools → Site Health → Info) contains most of this, exportable as text with one button. It is one of the most underused screens in WordPress.

Reading the plugin list like a diagnostician

You are not just counting plugins; you are looking for patterns:

  • Deactivated plugins. They still count as attack surface — a vulnerable file is exploitable whether or not the plugin is active. Rule: deactivated for no documented reason means deleted, after the baseline backup.
  • Duplicates by category. Two SEO plugins, three caching plugins, or two page builders indicate previous developers layering fixes without removing the old attempt. Pick winners deliberately, later.
  • Abandoned plugins. Check the plugin page on wordpress.org: no update in 2+ years and no compatibility flag for the current WordPress version means you should be pricing a replacement.
  • Nulled or unlicensed premium plugins. Premium plugins with no license key entered cannot receive updates — which means known vulnerabilities stay open forever. If the version string looks tampered with or the plugin came from a warez source, treat the whole site as potentially compromised.
  • The mystery custom plugin. Anything not on wordpress.org and not obviously commercial gets its code skimmed before you trust it. You are looking for the previous developer's site-specific glue — often important, never documented.

Step 3: Check integrity, not just versions

An up-to-date site can still be a compromised site. Three checks separate old and dusty from actively hostile:

  1. Core file verification: wp core verify-checksums compares every core file against the official hashes. Modified core files are either a very unwise customization or malware; both need investigating. The plugin equivalent, wp plugin verify-checksums --all, covers wordpress.org plugins.
  2. Look for files that should not exist. PHP files in wp-content/uploads/ are almost never legitimate: find wp-content/uploads -name '*.php'. Also skim the webroot for randomly named PHP files sitting next to wp-config.php.
  3. Check for unexpected scheduled tasks: wp cron event list. Malware loves WP-Cron for persistence; so do long-forgotten plugins. Anything with a hook name you cannot attribute to an installed plugin deserves a search through the codebase.

Also open wp-config.php and actually read it. You are checking that WP_DEBUG is false in production, noting any custom constants (a hardcoded API key is a finding), and confirming the security keys are set to real random values rather than put your unique phrase here. While you are there: wp config get table_prefix tells you if there are multiple installs sharing one database, which is its own delightful surprise.

Step 4: Database health

The database tells you things the dashboard hides. Start with size and shape:

  • wp db size --tables — sort by size mentally. A wp_options table over ~20 MB or a wp_postmeta table wildly larger than wp_posts suggests plugin data hoarding.
  • Autoloaded options are the classic inherited-site performance tax. Every autoloaded option loads on every single request. Check the total: SELECT SUM(LENGTH(option_value)) FROM wp_options WHERE autoload='yes'; — under 1 MB is healthy, and by the time you are past 3–4 MB you can usually measure the drag. The culprits are almost always rows left behind by deleted plugins.
  • Orphaned tables. Deleted plugins rarely clean up. Tables prefixed for plugins that no longer exist can be dropped — after the baseline backup, and after a week of nothing breaking.
  • Post revisions and transients. Thousands of revisions and expired transients are not dangerous, just heavy. wp transient delete --expired is a safe first cleanup; capping revisions with define('WP_POST_REVISIONS', 20); stops the growth.

Step 5: Baseline performance and the front of the house

Before you optimize anything, record how the site performs today — otherwise you can never demonstrate improvement, and demonstrating improvement is half the job when there is a client involved.

  • Run PageSpeed Insights or a WebPageTest run on the homepage and the two most important templates (a product page, a key landing page). Save the reports, not just the scores. Note Largest Contentful Paint and Time to First Byte specifically: a TTFB persistently above ~800 ms points at hosting or the absence of page caching, and no amount of image optimization will fix it.
  • Confirm what caching exists. Is there a page cache (host-level or plugin)? An object cache (wp cache type if the host provides Redis or Memcached)? Or nothing?
  • Click through the site like a customer: main navigation, search, the contact form (actually submit it — does the email arrive?), and checkout if there is one. Forms that silently fail are among the most common and most expensive inherited defects.
  • Check that the SSL certificate is valid, auto-renewing, and that HTTP redirects to HTTPS without a redirect chain.

The SEO five-minute check

You are not doing an SEO audit, but you are checking for landmines: is the site accidentally set to discourage search engines (Settings → Reading)? Does /robots.txt block anything alarming? Does an XML sitemap exist and load? Is there exactly one canonical domain (www or bare, not both serving 200s)? Each of these takes seconds to verify and weeks to notice when wrong.

Step 6: Write the handover document that should have existed

Everything above produces notes. Spend the last hour turning them into the one-page document you wish you had been given:

  • Access inventory (where everything lives, who holds credentials)
  • Stack summary: WordPress, PHP, theme and its origin, the plugins that matter and why each exists
  • Findings ranked into three buckets: urgent (security exposures, expired licenses, failing forms), soon (outdated PHP, plugin consolidation, database cleanup), and eventually (performance work, theme debt)
  • Anything you deliberately did not touch, and why

The three-bucket ranking is the deliverable. It converts an overwhelming pile of inherited weirdness into a sequenced plan a client can approve — and it establishes, in writing, which problems predate you.

What not to do in week one

A short list of tempting mistakes:

  • Do not mass-update everything on day one. Update in small batches with checks in between, starting with security releases. On a site with no staging environment, one plugin at a time is slower and dramatically easier to debug.
  • Do not switch themes, hosts, or page builders yet. These are project-sized decisions wearing quick-fix costumes.
  • Do not delete the previous developer's mystery code until you have grepped for what calls it. temp-fix-DO-NOT-DELETE is terrible engineering and also, occasionally, load-bearing.

An inherited WordPress site is rarely as bad as it looks in the first hour, and rarely as fine as the previous owner claimed. The audit is how you find out which. Do it once, write it down, and the site stops being a mystery you maintain and becomes a system you run.

Photo: RDNE Stock project on Pexels