The Initial Crisis
What started as a routine website maintenance call quickly revealed itself to be something much more serious. The client’s server had been compromised by malware, with CPU and RAM usage spiking to dangerous levels. The WordPress site was crawling at a snail’s pace, making it practically unusable for visitors.

On top of this technical nightmare, the site was bloated with unnecessary plugins that were further dragging down performance. The situation reminded me why we always say that prevention is better than cure. A compromised server isn’t just a technical problem—it’s a business emergency that affects everything from customer trust to search engine rankings.
What the Customer Really Wanted
At first glance, the client’s requests seemed straightforward enough. They wanted to add WhatsApp and email contact options to their website, and they wanted to change their WooCommerce “Add to Cart” buttons to “Inquire” buttons that would trigger email inquiries instead of actual purchases. Simple changes, right? That’s what I thought too.



The business logic made perfect sense. They were transitioning from direct sales to a more consultative approach where customers would reach out for quotes and personalized service. It’s a smart business model, especially for specialized products that require customer education and support.
The Reality of Implementation
Here’s where things got interesting, and by interesting, I mean complicated. What looked like a fifteen-minute modification turned into hours of custom coding work.
The server migration came first, naturally. With a virus-infected system, there was no choice but to start fresh. We followed our standard WordPress migration protocol, moving the entire site to a clean server environment.
WordPress migration to another server mainly includes the following steps:
1. Backup Original Website Data
Backup Files
# Package WordPress files
tar -czf wordpress_backup.tar.gz /path/to/wordpress/
Backup Database
# Export MySQL database
mysqldump -u username -p database_name > wordpress_backup.sql
2. Transfer Data to New Server
# Use scp to transfer files
scp wordpress_backup.tar.gz user@new-server:/path/to/destination/
scp wordpress_backup.sql user@new-server:/path/to/destination/
3. Restore on New Server
Extract Files
# Extract to website directory
tar -xzf wordpress_backup.tar.gz -C /var/www/html/
Restore Database
# Create new database
mysql -u root -p -e "CREATE DATABASE new_wordpress_db;"
# Import data
mysql -u username -p new_wordpress_db < wordpress_backup.sql
4. Update Configuration File
// ...existing code...
define('DB_NAME', 'new_wordpress_db');
define('DB_USER', 'new_username');
define('DB_PASSWORD', 'new_password');
define('DB_HOST', 'localhost');
// ...existing code...
5. Update Domain and URL (if domain changes)
-- Update URL in database
UPDATE wp_options SET option_value = 'https://new-domain.com' WHERE option_name = 'home';
UPDATE wp_options SET option_value = 'https://new-domain.com' WHERE option_name = 'siteurl';
6. Set File Permissions
Note that generally archive restoration can restore permissions, but different systems have different user uid
and gid
, so correct permissions must be set.
# Set correct permissions
chown -R www-data:www-data /var/www/html/
chmod -R 755 /var/www/html/
chmod 644 wp-config.php
7. Modify Corresponding Database Fields
If the new WordPress website directory is different from the previous one, you often need to modify corresponding fields in the database.
Example:
UPDATE hy_options SET option_value = REPLACE(option_value, '/home/wwwroot/www.hydebiolabs.com/', '/www/sites/www.hydebiolabs.com/index/') WHERE option_value LIKE '%/home/wwwroot/www.hydebiolabs.com/%';
8. Test Website
- Check if the website loads normally
- Verify backend login functionality
- Test if plugins and themes work properly
Important Notes:
- It’s recommended to test on the new server before migration
- Ensure the new server environment is compatible with the original server
- Update DNS records to point to the new server
- Consider using WordPress migration plugins like “All-in-One WP Migration” to simplify the process
This part, while time-consuming, was relatively straightforward—we’ve done it countless times before.
Adding the contact information was the easy part. A few widget placements and some basic HTML, and we had WhatsApp and email links prominently displayed.



But those “simple” button modifications? That’s where I learned a valuable lesson about making assumptions. Converting WooCommerce cart functionality to inquiry forms required custom CSS and JavaScript work that dug deep into the theme’s structure:
.woocommerce ul.products li.product h3 {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.add_to_cart_button span {
display: none;
}
.add_to_cart_button::after {
content: 'Inquire';
display: block;
color: inherit;
text-align: center;
}
function change_add_to_cart_links() {
?>
<script>
document.addEventListener('DOMContentLoaded', function() {
const addToCartButtons = document.querySelectorAll('a.add_to_cart_button');
addToCartButtons.forEach(function(button) {
button.href = 'mailto:info@hydebiolabs.com';
button.removeAttribute('data-product_id');
button.removeAttribute('data-product_sku');
button.removeAttribute('rel');
button.removeAttribute('data-wp-on--click');
button.classList.remove('ajax_add_to_cart');
});
});
</script>
<?php
}
add_action('wp_footer', 'change_add_to_cart_links');
We also tackled the plugin bloat issue, deactivating several unnecessary extensions that were consuming resources without adding real value to the user experience.

The Service Boundary Challenge
This project really made me think about where we draw the line between standard maintenance and custom development work. When a client asks to “just change a button,” it sounds like a quick fix. But when that button is integrated into a complex e-commerce system with AJAX functionality, database interactions, and theme-specific styling, it becomes a mini development project.
The challenge isn’t technical—we can solve these problems. The challenge is communicating the scope and setting proper expectations from the start. A client who expects a five-minute change might be surprised when they receive a quote for several hours of custom work.
This experience highlighted the importance of having clear service boundaries and a standardized process for handling requests that fall outside routine maintenance. We need to get better at quickly identifying when a “simple” request is actually a complex customization that requires development time and resources.
Moving Forward
Every project teaches us something, and this one reinforced several important lessons. First, we need clearer communication tools to help clients understand the difference between configuration changes and custom development. Second, we should establish standardized processes for common customizations so we can provide more accurate time estimates upfront.
The technical work was successful—the site is now running smoothly on a clean server, and the inquiry system is working exactly as the client envisioned. But the real value of this project lies in the lessons learned about managing client expectations and defining service boundaries.
Sometimes what appears simple on the surface requires diving deep into the technical foundation. That’s not a problem to be solved—it’s a reality to be managed through better communication and clearer processes from the very beginning of each project.