When a WP-SWEEP database clean-up wiped out my custom Advanced Scripts setup of over 50 custom snippets for a, I didn’t panic, I grabbed my dev tools and went full forensic surgeon on my WordPress database.
After running WP-Sweep to clean up unused terms and meta entries, I discovered that all my Advanced Scripts (the ones created via the Advanced Scripts plugin) had vanished from the WordPress admin interface. The PHP files were still safely in /wp-content/advanced-scripts/php/
, but the scripts no longer appeared in the UI. WP-Sweep had inadvertently deleted key metadata and term relationships used by the plugin.
The Clues Left Behind
On inspection, the scripts were still physically stored as PHP files, but the UI had nothing to display, the scripts were orphaned.
Initially, I combed through the database—posts
, postmeta
, and more, but came up empty. That’s when it clicked: the cleanup that was run had deleted orphaned terms, and that’s where the Advanced Scripts entries were tied.
To confirm, I created a brand new Advanced Script manually and checked the terms
and termmeta
tables again. Bingo. I could trace exactly how the new entry was structured and connected. From there, it was just a matter of reverse-engineering the relationships.
The Strategy
Rather than manually rebuilding each script entry through the Advanced Scripts UI, I took a smarter route.
I started by taking screenshots of all the PHP filenames in the /php/
directory and asked ChatGPT to list them out for me – thanks .
I wrote a series of SQL and PHP scripts to:
- Insert new entries into
terms
andtermmeta
, using the filenames to populate slugs and titles. - Recreate
term_relationships
that link each term to its associated script. - And finally, I used a PHP snippet to pull in the actual file contents and insert them into the
script_code
meta field.
Clean, precise, and way faster than starting from scratch.
?️ The Tools
This wasn’t just a plugin recovery, it was a full-on WordPress forensics operation. Here’s what I used to restore dozens of lost Advanced Scripts entries without losing my other site improvements:
? Google Sheets
Before I even touched the database, I used Google Sheets to process file names and generate clean, import-ready values. Some of the key formulas:
=LEFT(A1, 3)
– To extract the term ID from filenames=SPLIT(A1, "-")
– To separate words for slugs or display titles=CONCATENATE()
– To quickly assemble SQL value rows- Sort & Filter – To group, organise, and clean the data before export
? SQL
With the structure mapped out, I used custom SQL to:
- Recreate
wp_terms
,wp_term_taxonomy
, andwp_termmeta
entries - Assign hooks, priorities, types, statuses, and filenames for each script
- Restore the relationships between taxonomy terms and their metadata
? PHP
For importing file content:
$content = file_get_contents($filepath);
update_term_meta($term_id, 'script_code', $content);
This pulled in the full script from disk and injected it into the correct term_id
, all without touching the UI.
? Database Access (phpMyAdmin)
- I tracked down which tables Advanced Scripts uses (
terms
,termmeta
,term_taxonomy
) - I observed working entries and reverse-engineered the structure from there
- To prevent conflicts or accidental execution of duplicate scripts or corrupted code, I intentionally left
script_status
empty during the SQL re-import.
? First up, Find My PHP Files
All scripts were sitting safely (but uselessly) in: /wp-content/advanced-scripts/php/
117-myscript-abc.php
118-myscript-def.php
119-myscript-ghi.php
From these, I matched and rebuilt each script entry, preserving IDs, priority, hook, and status where relevant.
- SQL for controlled re-creation of metadata
- Custom PHP to bulk-import file contents directly into the DB
- A careful eye on
meta_id
,term_id
, and hook/priority combinations to keep everything tidy
? Step 1: Recreate Term Entries for Lost Scripts
Once I identified that the Advanced Scripts were stored in the terms
table (not posts
), I began reconstructing them using SQL. I made sure not to reuse deleted IDs and left gaps for future use or reserved IDs.
Here’s a sample of the SQL I used via phpMyAdmin to manually recreate 3 script terms:
INSERT INTO `wp_terms` (`term_id`, `name`, `slug`, `term_group`) VALUES
(117, '117-myscript-abc', '117-myscript-abc'', 0),
(118, '118-myscript-def', '118-myscript-def', 0),
(120, '119-myscript-ghi', '119-myscript-ghi', 0);
? Tip: You must also insert matching rows into the term_taxonomy
table after this step to define the taxonomy and link them properly.
? Step 2: Define the Taxonomy for Each Term
After inserting the term entries, I had to define their taxonomy so WordPress would treat them correctly as advanced_script
records. For Advanced Scripts, the taxonomy is typically something like erropix_scripts
.
Here’s the SQL I used to create corresponding taxonomy entries for each term:
INSERT INTO `wp_term_taxonomy` (`term_taxonomy_id`, `term_id`, `taxonomy`, `description`, `parent`, `count`) VALUES
(117, 117, 'erropix_scripts', '', 0, 0),
(118, 118, 'erropix_scripts', '', 0, 0),
(120, 120, 'erropix_scripts', '', 0, 0);
? Note: term_taxonomy_id
can match the term_id
for simplicity, especially when manually managing entries. Just be consistent.
?️ Step 3: Insert termmeta
for Each Script
Each Advanced Script entry stores its details in the wp_termmeta
table. For each term_id
, we insert metadata like the script’s title, file path, execution hook, but not the code yet.
Here’s the example for just one of the anonymised entries (term_id
= 117):
INSERT INTO `wp_termmeta` (`term_id`, `meta_key`, `meta_value`) VALUES
(117, 'script_title', 'myscript-abc'),
(117, 'script_filename', 'php/117-myscript-abc.php'),
(117, 'script_type', 'application/x-httpd-php'),
(117, 'script_hook', 'plugins_loaded'),
(117, 'script_location', 'all'),
(117, 'script_priority', '10'),
(117, 'script_status', ''), -- left intentionally blank to keep script disabled initially - published is the value to turn the script on.
(117, 'script_conditions', ''),
(117, 'script_shortcode', NULL),
(117, 'script_url', NULL),
(117, 'script_code', '');
⚠️ Note: I intentionally left script_status
blank. This prevents scripts from running immediately upon import, just in case a file contains duplicate logic or unexpected effects. It’s a safeguard while manually verifying each script’s behaviour before activation.
? Step 4: Import Script Contents into script_code
With the structure in place, it’s time to populate each script’s actual code from your /wp-content/advanced-scripts/php/
directory.
Here’s the PHP snippet that will hopefully blow your mind, and bring it all together – used inside an Advanced Script (or as a temporary must-use plugin):
<?php
add_action('init', function () {
if (!current_user_can('administrator')) return;
$scripts = [
117 => '117-myscript-abc.php',
118 => '118-myscript-def.php',
119 => '119-myscript-ghi.php',
];
$base = WP_CONTENT_DIR . '/advanced-scripts/php/';
global $wpdb;
foreach ($scripts as $term_id => $filename) {
$path = $base . $filename;
if (!file_exists($path)) {
echo "Missing: $filename<br>";
continue;
}
$code = file_get_contents($path);
// Check if script_code already exists
$meta_id = $wpdb->get_var($wpdb->prepare(
"SELECT meta_id FROM {$wpdb->prefix}termmeta WHERE term_id = %d AND meta_key = %s",
$term_id, 'script_code'
));
if ($meta_id) {
// Update existing
$wpdb->update("{$wpdb->prefix}termmeta",
['meta_value' => $code],
['meta_id' => $meta_id]
);
} else {
// Insert new
$wpdb->insert("{$wpdb->prefix}termmeta", [
'term_id' => $term_id,
'meta_key' => 'script_code',
'meta_value' => $code,
]);
}
echo "✔ Imported: $filename<br>";
}
// Optional: Only run once, then disable
// remove_action('init', __FUNCTION__);
});
✍️ Final Touch
You can now manually set script_status
to publish
for each verified script via SQL or WP admin if needed. Or… enable it in advanced scripts, when you’re confident everything is in order. ?
The Result
After executing the restoration strategy step-by-step, all Advanced Scripts were successfully recovered in bulk. Each script entry was rebuilt with its:
- Original filename (
script_filename
) - Fully populated metadata (
hook
,location
,priority
, and more) - Actual PHP code (
script_code
) pulled directly from the filesystem
Once the final step ran, importing the code into the database, the Advanced Scripts plugin recognised the entries immediately, as if nothing had ever happened.
There was no need to manually recreate dozens of entries through the WordPress admin interface. By restoring them programmatically via SQL and PHP, I saved hours of repetitive work and ensured consistency across all entries.
? As a precaution, I left script_status
blank on import so that the scripts wouldn’t auto-run before I’d had a chance to review them, allowing a safe and controlled reactivation process.
It was a bit like surgery, but with a successful recovery rate of 100%. ??
Basically a WordPress forensic surgeon at this point.
? Could I Have Just Restored from a Backup?
Technically, yes. I had a full database backup available.
But it wasn’t the right move.
That backup had been taken before I completed a major round of optimisations, including:
- WooCommerce performance improvements
- Image clean-up and storage reduction
- WebP and thumbnail size optimisation
- LiteSpeed + caching fine-tuning
- CSS/JS deferrals and other load speed tweaks
Restoring the backup would have meant losing all of that work, just to recover a few deleted scripts. It would’ve set me back hours, not to mention undoing all the progress I’d made on performance.
So instead, I went the forensic route: manually rebuilding what was lost from scratch, while keeping all the speed and SEO wins intact. ?️
? The Backup Dilemma, Who Pays?
Here’s where it gets tricky.
The server hadn’t been running automated backups for a while due to disk space issues, mainly caused by thousands of unnecessary thumbnails and WebP duplicates from unused product images.
I hadn’t taken a manual backup during the day either (lesson learned). But the bigger issue? The client had declined to pay for a professional backup system with incremental restore points and retention settings.
Then it happened.
I ran WP-Sweep to clean up “orphaned terms,” not realising that Advanced Scripts stored all its code metadata in taxonomy tables, not posts. Totally non-standard, and completely nuked the scripts in one click. ?
? So… Should I Charge for the Recovery?
That’s the ethical grey area.
It was my action that caused the data loss. But the lack of safeguards, no backups, no system monitoring, made it far more painful than it should’ve been.
I’ll probably chalk most of this up to experience.
But I’ll also be updating my terms to strongly recommend (or even require) clients to invest in professional backups. Because the cost of prevention is nothing compared to the cost of recovery.
Takeaways
- Always back up before sweeping or deleting anything in WordPress, especially with plugins that use unconventional data structures.
- Some plugins (like Advanced Scripts) store critical info in terms and termmeta, not posts or postmeta. That makes them fragile and more vulnerable to cleanup plugins.
- With access to the database, and a bit of clever code , you can rebuild almost anything.
- This was a reminder that backups aren’t just a “nice to have”, they’re your safety net. But if all else fails…