← Blog

WordPress

WordPress audit checklist: scoring the Elementor stack tax

A Dutch marketing lead bills 14 hours a month to keep the Elementor Pro plus WP Rocket plus WPML stack alive. Here is the audit we run before any rebuild.

Jacob Molkenboer· Founder · A Brand New Company· 30 Aug 2025· 9 min
Open leather ledger with cloth bookmark, brass tag, green index card, broken red wax seal on ivory paper.

It is Wednesday, 11:40 in the morning. The marketing lead at a Utrecht engineering firm opens her August timesheet and counts again. Fourteen hours, against WordPress, in a month where nothing on the site was supposed to change. Three of those hours went to rolling back a WP Rocket update that broke the Elementor Pro header on the Dutch site but not the English one. Two went to a WPML string-translation job that should have taken twenty minutes. The rest is the slow rot of a six-year-old stack that nobody hates enough to replace and nobody likes enough to defend.

We see this exact pattern on roughly half the Dutch SMEs we audit between five and fifteen million in revenue. The estate is always some flavor of WordPress 6.5 plus Elementor Pro plus WP Rocket plus WPML, sitting on a shared host with forty-seven plugins, three of which the lead does not recognise. The site still converts. The cost is hidden inside a marketing salary.

This post is the audit we run before we touch anything. It is a single afternoon of work and it answers three questions: what is each plugin update going to break, where is the content locked into the builder, and which pages would survive a rebuild without burning your Google Ads quality score to the ground.

The fourteen-hour bleed pattern

The number is consistent enough to be useful. When a marketing lead is billing more than ten hours a month to a WordPress estate, the bleed almost always sits in the same three places.

The first is the Elementor plus WP Rocket interaction. WP Rocket's "remove unused CSS" feature ships every Elementor widget's stylesheet to the browser through a separate pipeline than the rest of the theme. After an Elementor Pro point release, that pipeline goes stale, the header collapses on mobile, and someone has to deactivate either the cache or the rebuild-CSS toggle until WP Rocket ships a compatibility update. This happens about every six weeks.

The second is WPML's translation tables. WPML stores post translations in wp_icl_translations with foreign keys pointing into wp_posts. When an editor deletes a Dutch page through the admin UI, the English and German copies stay behind but lose their parent reference. They surface six months later in a sitemap audit nobody asked for.

The third is the plugin update queue itself. A typical mid-size estate has between thirty and fifty active plugins. Two or three are abandoned. One is a paid Elementor add-on that has not shipped a release in fourteen months. The lead knows this and does not click "update all" because she has been burned, so the queue grows until it gets cleared in a panic after a CVE drops.

The audit is the thing that converts this bleed into a list someone can fix in a sprint.

Plugin-update blast radius

We score every active plugin on a 0 to 3 scale across four axes. The output is a single number per plugin called the blast radius.

  • Surface coverage. Does the plugin touch templates, the database schema, or both? A caching plugin scores 3. A SEO meta box scores 1.
  • Update cadence. Has the plugin shipped a release in the last 90 days? A stale plugin scores 3 because nobody has tested it against current WordPress.
  • Override depth. Does the plugin hook into the_content, pre_get_posts, or the REST API? Deep hooks score 3 because a regression in one of those filters cascades silently.
  • Replaceability. If the plugin disappeared tomorrow, how many hours to replace it? Less than two scores 0. More than forty scores 3.

The blast radius is the sum. Anything scoring 8 or higher gets a row in the rebuild ledger. Anything 11 or 12 is the plugin you do not touch until you have a staging clone and a rollback plan written out by hand.

A quick way to dump the active plugin list with last-update timestamps from the command line, assuming you have WP-CLI on the server:

wp plugin list --status=active --fields=name,version,update,update_version \
  --format=csv > active-plugins.csv

# Cross-reference against the .org repository for last-commit date
for slug in $(wp plugin list --status=active --field=name); do
  curl -s "https://api.wordpress.org/plugins/info/1.0/${slug}.json" \
    | jq -r "[\"$slug\", .last_updated, .tested] | @csv"
done > plugin-freshness.csv

Premium plugins (Elementor Pro, WP Rocket, WPML) will not appear in the .org API. For those we check the vendor changelog by hand. It is twenty minutes for the whole estate, and it surfaces every license that lapsed without anyone noticing.

Custom post type lock-in

This is the part of the audit that decides whether a rebuild is a refactor or a full migration.

Every Elementor Pro template is stored as a custom post type (elementor_library). The page content itself is serialised into a _elementor_data post meta field as a single JSON blob. That blob references widget IDs that only mean anything if Elementor Pro is loaded. Strip the plugin and the page renders as a wall of empty divs.

The same pattern applies to most builder plugins and to a handful of CRM plugins (HubSpot, ActiveCampaign) that store form definitions in custom tables. WPML adds its own layer: each translated post is a separate row in wp_posts linked through wp_icl_translations, with string translations sitting in a third table that has its own backup model.

The audit step is mechanical. For each custom post type, you count three things:

-- Posts that depend on Elementor for rendering
SELECT COUNT(*) AS elementor_locked
FROM wp_posts p
JOIN wp_postmeta m ON m.post_id = p.ID
WHERE p.post_status = 'publish'
  AND m.meta_key = '_elementor_data'
  AND m.meta_value LIKE '%"widgetType"%';

-- Posts in custom post types defined by plugins (not the theme)
SELECT post_type, COUNT(*) AS n
FROM wp_posts
WHERE post_status = 'publish'
  AND post_type NOT IN ('post', 'page', 'attachment', 'revision', 'nav_menu_item')
GROUP BY post_type
ORDER BY n DESC;

-- WPML translation pairs that have lost their reference
SELECT t.element_type, COUNT(*) AS orphans
FROM wp_icl_translations t
LEFT JOIN wp_posts p ON p.ID = t.element_id
WHERE t.element_type LIKE 'post_%'
  AND p.ID IS NULL
GROUP BY t.element_type;

The output of that third query is the one that surprises clients. We see between 40 and 600 orphan rows on a typical mid-size site. They are not breaking anything today. They will break the migration script if you do not know they are there.

Warning

If elementor_locked is over 70% of your published pages, you are not migrating off Elementor. You are rewriting the site. Price that into the conversation before you promise anyone a headless rebuild by Q4.

The three-page survival test

Here is the test that decides whether a partial rebuild is worth the risk. Pick the three pages that drive the most paid traffic. Usually these are the homepage, one service page, and one landing page tied to an active Google Ads campaign. For each one, answer four questions on paper, not in a slide.

  1. What is the URL slug, and does anything else on the site depend on it? AdWords destination URLs, email signatures, printed brochures, and Google Business profiles all hard-code slugs. If the slug changes, redirects are not optional.
  2. What is the H1, the meta title, and the schema markup? These three together drive the landing page experience score that feeds the Google Ads quality score. Google's landing page experience documentation is explicit that destination relevance and load speed dominate the rating.
  3. Which plugins does the page actually need to render? Open the page, view source, then deactivate each plugin one at a time in a staging clone. If the page survives without Elementor, half your migration problem is solved. If it does not, write down which widgets it uses.
  4. What is the form, and where do submissions go? A landing page without a working form is worse than no landing page. We have seen rebuilds ship with the contact form pointing at a CRM endpoint that was deprecated two years earlier.

A page that passes all four questions can be rebuilt headless (Next.js, Astro, Eleventy, anything) in a week without losing AdWords performance. A page that fails question three has a builder dependency that needs a content migration before the URL can move. A page that fails question four needs a meeting with whoever owns the CRM before anything else happens.

AdWords landing slot preservation

This is the rule we tell every client and almost every client wants to argue about: do not change the URL of an active Google Ads landing page during a rebuild. Not the slug, not the protocol, not the trailing slash. The quality score is computed partly on historical CTR for that exact destination URL, and a 301 redirect resets the clock on that history. Google has never confirmed this directly. Every paid-search lead we have worked with for ten years has the same scar.

The implication for the audit is simple. The three highest-spend landing URLs are immovable. The rebuild either serves the same path through the new stack (a reverse proxy in front of the old WordPress install, or a static export with matched slugs) or it does not touch those URLs at all. Everything else is on the table.

While you are at it, check the canonical tag. WPML has a habit of pointing the canonical at the default-language version even when the user landed on a translated URL through a paid ad. That is one of the few audit findings that costs measurable revenue inside thirty days.

Running the audit in one afternoon

The whole audit fits in a half-day if you have admin access and a staging clone. The deliverable is a single spreadsheet with three tabs: plugin blast radius, custom post type inventory, and the three-page survival sheet. We send the client a one-page summary on top of that with the headline number, which is the projected monthly hours after the rebuild.

On a six-year-old estate, the only scalable cleanup is a fresh install of WordPress 6.5 (Shirley, shipped April 2024) with the content imported through a curated export, not a database dump. A dump carries every orphan translation row, every lapsed plugin's options entries, and every WPML join you spent the audit identifying. A curated export means a defined post type allow-list, a meta-key allow-list, and a media-folder pass that drops the orphaned uploads from 2019. Anything less leaves you maintaining the bleed.

When we ran this audit for a Rotterdam logistics firm last spring, the WPML estate had 312 orphan translation rows and an Elementor Pro license that had lapsed eleven months earlier. We rebuilt three pages headless on a Next.js front-end, kept WordPress as the editorial back-end for everything else, and the marketing lead's WordPress hours dropped to two per month. The work fits what we usually call a legacy migration, and the audit is the cheap part. The rebuild is where the discipline matters.

Pick the three URLs you most fear losing. Open them in three browser tabs. If you cannot name, from memory, which plugins each page needs to render, your audit starts there.

Key takeaway

A WordPress audit answers three questions: what each plugin update will break, where the builder locks content, and which URLs you cannot afford to change.

FAQ

How long does the audit take?

Half a day if you have admin access and a staging clone. The deliverable is a three-tab spreadsheet plus a one-page summary with the projected monthly hours after a rebuild.

Can I just deactivate Elementor and rewrite the pages?

Only if fewer than 70% of your published pages depend on Elementor for rendering. Above that threshold you are rewriting the site, not migrating off the builder, and the budget needs to match.

Will moving to a headless front-end hurt my Google Ads quality score?

Not if you preserve the exact URL, H1, meta title, and form destination on every active landing page. Quality score history is tied to the destination URL, so even a 301 redirect resets the clock.

What is the smallest version of this audit I can run myself?

Open your three highest-spend landing pages. For each one, list the plugins it needs to render. If you cannot name them from memory, you already have the start of an audit.

wordpresslegacy sitesmigrationworkflowarchitecturestrategy

Building something?

Start a project