Moving your WordPress website can be a daunting task, but with the right knowledge and preparation, it becomes a manageable process. Whether you’re changing domains, upgrading hosting, or restructuring your site architecture, this comprehensive guide will walk you through every step of the WordPress migration process.
Understanding WordPress Site URLs
Before diving into migration techniques, it’s crucial to understand the two fundamental URL settings in WordPress:
- WordPress Address (URL): This is where your WordPress core files reside
- Site Address (URL): This is the address visitors type in their browser to reach your site
Both settings should include the https:// part and should not have a trailing slash / at the end. These settings control how WordPress displays URLs throughout your site, including the admin section and frontend.
Why WordPress Migration Becomes Necessary
Several scenarios might require you to migrate your WordPress site:
- Domain Changes: Rebranding or switching to a better domain name
- Hosting Migration: Moving to a better hosting provider
- Server Changes: Upgrading server infrastructure
- Site Restructuring: Moving WordPress to a subdirectory or root directory
- Development to Production: Moving from staging to live environment
- HTTP to HTTPS: Implementing SSL certificates
Preparation: The Key to Successful Migration
Backup Everything
Before attempting any migration, create comprehensive backups:
- Database Backup: Export your WordPress database via phpMyAdmin or WP-CLI
- File Backup: Download all WordPress files and directories
- Configuration Backup: Save your wp-config.php file separately
- Plugin/Theme Settings: Document custom configurations
Test Environment Setup
Always test migrations in a staging environment before going live:
## Create a test subdirectory
mkdir /var/www/html/test-site
## Copy files to test location
cp -r /var/www/html/wordpress/* /var/www/html/test-site/
Migration Methods: From Simple to Advanced
Method 1: Using wp-config.php (Quick Fix)
For temporary URL changes, add these lines to your wp-config.php:
define('WP_HOME', 'https://example.com');
define('WP_SITEURL', 'https://example.com');
Pros: Quick and immediate Cons: Hard-coded values, can’t edit in WordPress admin anymore
Method 2: functions.php Approach (Temporary Fix)
If you have FTP access but can’t access WordPress admin:
- Access your active theme’s functions.php file
- Add these lines after the opening
<?phptag:
update_option('siteurl', 'https://example.com');
update_option('home', 'https://example.com');
- Upload the file and visit your admin panel
- Important: Remove these lines after the site is working
Method 3: WordPress Relocate Method
WordPress includes an automatic relocation method:
- Edit wp-config.php and add before “That’s all, stop editing!”:
define('RELOCATE', true);
- Visit
https://yoursite.com/wp-login.php - Login normally
- Check Settings > General to verify URLs
- Remove the RELOCATE constant afterward
Security Warning: Never leave RELOCATE constant in wp-config.php as it creates security vulnerabilities.
Method 4: Direct Database Editing
For precise control, edit URLs directly in the database:
- Access phpMyAdmin
- Select your WordPress database
- Find wp_options table (prefix may vary)
- Edit the ‘siteurl’ and ‘home’ rows
- Update option_value to new URLs
Critical: Always backup your database before making direct edits!
Advanced Migration Scenarios
Moving Between Servers
When migrating to a new server:
- Backup Everything: Complete site and database backup
- Export Database: Use phpMyAdmin or WP-CLI
- Transfer Files: Use FTP, SFTP, or rsync
- Import Database: Create new database and import
- Update wp-config.php: Modify database credentials
- Update URLs: Use one of the methods above
- Test Thoroughly: Check all functionality
Domain Name Changes
Changing domains requires special attention to serialized data:
## Using WP-CLI (recommended)
wp search-replace 'olddomain.com' 'newdomain.com' --skip-columns=guid
## Or use specialized plugins like:
## - Velvet Blues Update URLs
## - Better Search Replace
Important: Never update the GUID column in wp_posts table. GUID stands for Globally Unique Identifier and should never change to maintain feed reader compatibility.
Subdirectory to Root Migration
Moving WordPress from a subdirectory to root:
- Update URLs in WordPress Admin: Settings > General
- Copy Files: Move WordPress files to new location
- Update .htaccess: Modify rewrite rules
- Update Permalinks: Resave permalink structure
- Check Internal Links: Update hardcoded URLs
Multisite Migration
WordPress Multisite requires additional considerations:
- Backup Network: All sites and databases
- Edit wp-config.php: Update multisite constants
- Update .htaccess: Modify multisite rewrite rules
- Database Updates: Update wp_blogs and wp_site tables
- Individual Site Options: Update each site’s options tables
Post-Migration Checklist
Immediate Actions
- Test frontend functionality
- Verify admin access
- Check all forms and submissions
- Test e-commerce functionality
- Verify user login/registration
SEO Considerations
- Implement 301 redirects from old URLs
- Update sitemap.xml
- Submit new sitemap to search engines
- Update Google Analytics property
- Verify Google Search Console
Performance Optimization
- Clear all caches
- Optimize database tables
- Check plugin compatibility
- Test site speed
- Verify SSL certificate
Common Migration Problems and Solutions
White Screen of Death
Usually caused by:
- Memory limit exhaustion
- Plugin conflicts
- Theme incompatibility
Solution: Increase memory limit in wp-config.php:
define('WP_MEMORY_LIMIT', '256M');
Database Connection Errors
Check wp-config.php settings:
define('DB_NAME', 'database_name');
define('DB_USER', 'username');
define('DB_PASSWORD', 'password');
define('DB_HOST', 'localhost');
Mixed Content Issues
HTTP resources on HTTPS pages cause security warnings:
## Find mixed content
grep -r "http://" wp-content/
Image and Media Link Problems
Update media URLs in database:
UPDATE wp_posts SET post_content = REPLACE(post_content,'olddomain.com/wp-content/uploads','newdomain.com/wp-content/uploads');
Tools and Plugins for Migration
Recommended Migration Plugins
- All-in-One WP Migration: Complete site migration tool
- Duplicator: Create migration packages easily
- WP Migrate DB: Database migration specialist
- Velvet Blues Update URLs: URL updating tool
Command Line Tools
## WP-CLI database export
wp db export backup.sql
## WP-CLI database import
wp db import backup.sql
## Search and replace
wp search-replace 'old-url' 'new-url' --dry-run
Security Considerations During Migration
- Use HTTPS: Ensure SSL is configured on new server
- Update File Permissions: Secure wp-config.php (600) and directories (755)
- Remove Migration Scripts: Delete temporary files and constants
- Update Security Keys: Generate new WordPress keys in wp-config.php
- Monitor Logs: Watch for unusual activity post-migration
Performance Optimization After Migration
Database Optimization
OPTIMIZE TABLE wp_posts;
OPTIMIZE TABLE wp_postmeta;
OPTIMIZE TABLE wp_options;
Caching Configuration
- Configure page caching
- Set up browser caching
- Enable CDN integration
- Optimize database caching
Testing and Validation
Functionality Testing
- Navigation: All menu items work correctly
- Forms: Contact forms and submissions function
- Search: Site search returns results
- Comments: Comment system works
- Media: Images and videos load properly
SEO Validation
- Meta Tags: Titles and descriptions display correctly
- Canonical URLs: Point to new domain
- Structured Data: Schema markup validates
- Internal Links: All links work and redirect properly
Maintenance Post-Migration
Monitoring
- Set up uptime monitoring
- Monitor Google Search Console for errors
- Track analytics for traffic patterns
- Watch for 404 errors in logs
Ongoing Optimization
- Regular database optimization
- Image optimization and compression
- Plugin performance monitoring
- Security scan implementation
FAQ Section
Q: How long does a WordPress migration typically take?
A: Simple migrations can take 30 minutes to 2 hours, while complex multisite migrations may require 4-8 hours including testing and troubleshooting.
Q: Will my SEO rankings be affected by migration?
Q: Do I need to update all plugins after migration?
Q: What’s the difference between WP_HOME and WP_SITEURL?
Q: Should I migrate during business hours?
Q: How do I handle email forms during migration?
Q: What if I break something during migration?
Q: Can I migrate WordPress without downtime?
Q: Do I need to update my SSL certificate?
Q: How do I handle large databases during migration?
Q: Should I delete the old site after migration?
Q: What about user data and passwords?
Q: How do I update Google Analytics after migration?
Q: What’s the best way to test a migration?
Q: Do I need to update my robots.txt file?
Q: How do I handle custom post types and taxonomies?
Q: What about API integrations and webhooks?
Q: Should I use a migration service?
Real-World Migration Case Studies
Case Study 1: E-commerce Domain Migration
Scenario: A popular online store with 50,000+ products needed to migrate from store-old.com to brandnew.com while maintaining SEO rankings and customer trust.
Challenges Faced:
- Massive product database with complex variations
- Active shopping cart sessions during migration
- Third-party payment gateway integrations
- Customer email campaigns with old domain links
Migration Strategy:
-
Pre-migration preparation (2 weeks):
- Created complete site backup including customer data
- Set up temporary staging environment
- Tested all payment gateway integrations
- Prepared email templates for customer notification
-
Technical implementation (4 hours):
- Used WP-CLI for database URL replacement
- Implemented custom 301 redirect rules
- Updated all third-party API endpoints
- Configured SSL certificate for new domain
-
Post-migration optimization (1 week):
- Monitored Google Search Console for indexing issues
- Updated all marketing automation workflows
- Implemented enhanced tracking for migration impact
- Conducted customer satisfaction survey
Results:
- 98% of SEO rankings maintained within 2 weeks
- Zero data loss during migration
- Customer complaints reduced by 75% with proper communication
- 15% increase in site speed due to new hosting infrastructure
Key Lessons Learned:
- Customer communication is as important as technical execution
- Testing payment gateways in staging environment prevents revenue loss
- Having rollback plan ready provides confidence during execution
Case Study 2: Multisite Network Migration
Scenario: A educational institution with 200+ subdomain sites needed to migrate from shared hosting to dedicated cloud infrastructure.
Technical Complexity:
- 201 individual WordPress sites
- Custom user roles and permissions across sites
- Shared media library with 100GB+ of content
- Complex plugin dependencies between sites
Migration Approach:
-
Network Analysis Phase:
- Mapped all site interdependencies
- Identified custom plugin configurations
- Documented user role hierarchies
- Analyzed media library usage patterns
-
Staging Environment Setup:
- Replicated exact server configuration
- Created automated testing scripts
- Implemented performance monitoring
- Set up rollback procedures
-
Phased Migration:
- Migrated 10 pilot sites first
- Documented and refined process
- Batch migrated remaining sites
- Continuous monitoring and optimization
Technical Solutions:
## Custom script for batch multisite migration
#!/bin/bash
for site in $(wp site list --field=url); do
echo "Migrating $site"
wp search-replace 'old-domain.com' 'new-domain.com' --url=$site
wp cache flush --url=$site
done
Outcomes:
- 99.8% uptime during migration process
- 40% improvement in page load times
- Zero data corruption across all sites
- Simplified administration through centralized management
Case Study 3: HTTP to HTTPS Migration with Mixed Content Resolution
Scenario: A content-heavy blog with 10,000+ posts and extensive media library needed HTTPS implementation.
Mixed Content Challenges:
- Hardcoded HTTP links in post content
- External resources without HTTPS alternatives
- Embedded iframes from non-secure sources
- Custom CSS with HTTP references
Comprehensive Solution:
- Content Audit and Cleanup:
-- Find and replace HTTP references in posts
UPDATE wp_posts
SET post_content = REPLACE(post_content, 'http://example.com', 'https://example.com')
WHERE post_content LIKE '%http://example.com%';
-- Update guid fields (carefully!)
UPDATE wp_posts
SET guid = REPLACE(guid, 'http://example.com', 'https://example.com')
WHERE guid LIKE 'http://example.com%';
- Plugin Configuration Updates:
// Custom functions.php additions for HTTPS enforcement
add_action('template_redirect', function() {
if (!is_ssl() && !is_admin()) {
wp_redirect('https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], 301);
exit;
}
});
- Advanced .htaccess Configuration:
## Force HTTPS for all traffic
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
## Handle mixed content in WordPress
RewriteCond %{HTTP_REFERER} !^https://
RewriteRule ^(.*)$ - [F]
Performance Impact:
- Initial 5% traffic dip during first week
- Full recovery within 3 weeks
- 10% improvement in search rankings
- Enhanced user trust and security metrics
Advanced Migration Techniques
Database Migration Optimization Strategies
Handling Large Databases Efficiently
For databases exceeding 1GB, standard export/import methods often fail. Here are advanced techniques:
Method 1: Chunked Export with WP-CLI
## Export in chunks for large databases
wp db export --tables=wp_posts,wp_postmeta --add-drop-table
wp db export --tables=wp_options,wp_users,wp_usermeta --add-drop-table
## Combine and import separately
mysql new_database < chunk1.sql
mysql new_database < chunk2.sql
Method 2: Custom PHP Script for Memory Management
<?php
// Custom database migration script
set_time_limit(0);
ini_set('memory_limit', '1024M');
$source = new mysqli('localhost', 'user', 'pass', 'source_db');
$target = new mysqli('localhost', 'user', 'pass', 'target_db');
// Migrate in batches of 1000 records
$offset = 0;
$batch_size = 1000;
do {
$result = $source->query("SELECT * FROM wp_posts LIMIT $offset, $batch_size");
$count = $result->num_rows;
while ($row = $result->fetch_assoc()) {
$columns = implode(',', array_keys($row));
$values = implode(',', array_map([$target, 'real_escape_string'], $row));
$target->query("INSERT INTO wp_posts ($columns) VALUES ($values)");
}
$offset += $batch_size;
} while ($count == $batch_size);
?>
Serialized Data Handling
WordPress stores many settings as serialized PHP data, which breaks when URL lengths change:
Advanced Serialization Fix:
<?php
// Fix serialized data after URL changes
function fix_serialized_urls($old_url, $new_url) {
global $wpdb;
$options = $wpdb->get_results("SELECT option_id, option_value FROM $wpdb->options WHERE option_value LIKE '%$old_url%'");
foreach ($options as $option) {
$fixed_value = str_replace($old_url, $new_url, $option->option_value);
// Check if it's serialized data
if (is_serialized($fixed_value)) {
$unserialized = unserialize($fixed_value);
if ($unserialized !== false) {
$fixed_value = serialize($unserialized);
}
}
$wpdb->update(
$wpdb->options,
['option_value' => $fixed_value],
['option_id' => $option->option_id]
);
}
}
?>
Custom Migration Scripts Development
Automated Migration Framework
Create a comprehensive migration automation script:
#!/bin/bash
## WordPress Migration Automation Script
set -e # Exit on any error
## Configuration
OLD_DOMAIN="old-site.com"
NEW_DOMAIN="new-site.com"
BACKUP_DIR="/path/to/backups"
STAGING_DIR="/path/to/staging"
LOG_FILE="$BACKUP_DIR/migration_$(date +%Y%m%d_%H%M%S).log"
## Logging function
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
## Pre-migration checks
pre_migration_checks() {
log "Starting pre-migration checks"
# Check WordPress installation
if ! wp core is-installed --path=/var/www/html; then
log "ERROR: WordPress installation not found"
exit 1
fi
# Check database connection
if ! wp db check --path=/var/www/html; then
log "ERROR: Database connection failed"
exit 1
fi
# Create backup directory
mkdir -p "$BACKUP_DIR"
mkdir -p "$STAGING_DIR"
log "Pre-migration checks completed"
}
## Backup creation
create_backups() {
log "Creating comprehensive backups"
# Database backup
wp db export "$BACKUP_DIR/database_$(date +%Y%m%d_%H%M%S).sql" --path=/var/www/html
# Files backup
tar -czf "$BACKUP_DIR/files_$(date +%Y%m%d_%H%M%S).tar.gz" /var/www/html
# Configuration backup
cp /var/www/html/wp-config.php "$BACKUP_DIR/wp-config_$(date +%Y%m%d_%H%M%S).php"
log "Backups completed successfully"
}
## URL replacement
replace_urls() {
log "Starting URL replacement process"
# Core WordPress URLs
wp search-replace "$OLD_DOMAIN" "$NEW_DOMAIN" --skip-columns=guid --path=/var/www/html
# Additional URL replacements in specific tables
wp db query "UPDATE wp_postmeta SET meta_value = REPLACE(meta_value, '$OLD_DOMAIN', '$NEW_DOMAIN') WHERE meta_value LIKE '%$OLD_DOMAIN%'" --path=/var/www/html
log "URL replacement completed"
}
## Post-migration validation
post_migration_validation() {
log "Starting post-migration validation"
# Test site accessibility
if curl -f -s "https://$NEW_DOMAIN" > /dev/null; then
log "Site is accessible"
else
log "ERROR: Site is not accessible"
exit 1
fi
# Test WordPress admin
if curl -f -s "https://$NEW_DOMAIN/wp-admin/" > /dev/null; then
log "WordPress admin is accessible"
else
log "ERROR: WordPress admin is not accessible"
exit 1
fi
# Check database integrity
wp db check --path=/var/www/html
log "Post-migration validation completed"
}
## Main execution
main() {
log "Starting WordPress migration process"
pre_migration_checks
create_backups
replace_urls
post_migration_validation
log "Migration completed successfully"
}
## Execute main function
main
Performance Optimization Strategies
Server Configuration Optimization
Nginx Configuration for Migrated Sites
server {
listen 80;
server_name new-site.com www.new-site.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name new-site.com www.new-site.com;
root /var/www/html;
index index.php index.html;
# SSL Configuration
ssl_certificate /path/to/ssl/cert.pem;
ssl_certificate_key /path/to/ssl/private.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
# WordPress-specific configuration
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# Performance optimizations
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
}
# Caching configuration
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
}
PHP Optimization for Migration Performance
; PHP configuration optimized for WordPress migration
memory_limit = 512M
max_execution_time = 300
max_input_time = 300
upload_max_filesize = 64M
post_max_size = 64M
max_input_vars = 3000
; OPcache configuration for better performance
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=2
opcache.fast_shutdown=1
Database Performance Tuning
MySQL Configuration Optimization
-- MySQL optimization for WordPress
SET GLOBAL innodb_buffer_pool_size = 1073741824; -- 1GB
SET GLOBAL innodb_log_file_size = 268435456; -- 256MB
SET GLOBAL innodb_flush_log_at_trx_commit = 2;
SET GLOBAL innodb_flush_method = O_DIRECT;
-- Query cache configuration
SET GLOBAL query_cache_type = ON;
SET GLOBAL query_cache_size = 67108864; -- 64MB
Database Indexing Strategy
-- Add indexes for better performance
ALTER TABLE wp_posts ADD INDEX idx_post_type_status (post_type, post_status);
ALTER TABLE wp_postmeta ADD INDEX idx_meta_key_value (meta_key, meta_value(191));
ALTER TABLE wp_options ADD INDEX idx_autoload (autoload, option_name);
-- Optimize large tables
OPTIMIZE TABLE wp_posts;
OPTIMIZE TABLE wp_postmeta;
OPTIMIZE TABLE wp_options;
Advanced Troubleshooting Guide
Complex Migration Issues and Solutions
Issue 1: Serialized Data Corruption
Problem: After URL replacement, theme options and plugin settings become corrupted.
Diagnosis:
<?php
// Check for corrupted serialized data
function check_serialized_data() {
global $wpdb;
$corrupted = $wpdb->get_results("
SELECT option_id, option_name
FROM {$wpdb->options}
WHERE option_value LIKE '%:%'
AND (option_value NOT LIKE 'a:%' OR option_value NOT LIKE '%;\"%\";%')
");
foreach ($corrupted as $option) {
echo "Corrupted option: {$option->option_name}\n";
}
}
?>
Solution:
<?php
// Advanced serialized data repair
function repair_serialized_data($old_length, $new_length) {
global $wpdb;
// Get all serialized options
$serialized_options = $wpdb->get_results("
SELECT option_id, option_value
FROM {$wpdb->options}
WHERE option_value REGEXP '^[aO]:[0-9]+:'
");
foreach ($serialized_options as $option) {
$data = $option->option_value;
// Update length references in serialized data
$pattern = '/s:([0-9]+):\"(.*?)\";/s';
$callback = function($matches) use ($old_length, $new_length) {
$length = strlen($matches[2]);
return 's:' . $length . ':"' . $matches[2] . '";';
};
$repaired = preg_replace_callback($pattern, $callback, $data);
if ($repaired !== $data) {
$wpdb->update(
$wpdb->options,
['option_value' => $repaired],
['option_id' => $option->option_id]
);
}
}
}
?>
Issue 2: Memory Exhaustion During Large Database Migration
Problem: PHP memory limits exceeded during database import/export.
Solutions:
Method 1: Chunked Processing
<?php
// Process database in chunks to avoid memory issues
function process_database_in_chunks($table, $chunk_size = 1000) {
global $wpdb;
$offset = 0;
do {
$results = $wpdb->get_results("
SELECT * FROM $table
LIMIT $offset, $chunk_size
");
foreach ($results as $row) {
// Process each row
process_row($row);
}
$offset += $chunk_size;
// Clear memory
$wpdb->flush();
} while (count($results) === $chunk_size);
}
?>
Method 2: Streaming Database Export
## Use mysqldump with compression for large databases
mysqldump --single-transaction --quick --lock-tables=false \
--host=localhost --user=username --password=password \
database_name | gzip > backup.sql.gz
## Import with streaming
gunzip < backup.sql.gz | mysql -u username -p database_name
Issue 3: Plugin Compatibility After Migration
Problem: Plugins fail to work after URL changes due to hardcoded references.
Systematic Solution:
- Create Plugin Compatibility Checker:
<?php
// Plugin compatibility checker
function check_plugin_compatibility() {
$plugins = get_option('active_plugins');
$issues = [];
foreach ($plugins as $plugin_path) {
$plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin_path);
// Check for hardcoded URLs in plugin files
$plugin_files = glob(WP_PLUGIN_DIR . '/' . dirname($plugin_path) . '/*.php');
foreach ($plugin_files as $file) {
$content = file_get_contents($file);
// Look for potential hardcoded URLs
if (preg_match('/https?:\/\/[^\s"\'<]+/', $content, $matches)) {
$issues[] = [
'plugin' => $plugin_data['Name'],
'file' => $file,
'hardcoded_urls' => $matches
];
}
}
}
return $issues;
}
?>
- Automated Plugin URL Updater:
<?php
// Update plugin configurations with new URLs
function update_plugin_configurations($old_url, $new_url) {
global $wpdb;
// Update plugin options
$plugin_options = $wpdb->get_results("
SELECT option_name, option_value
FROM {$wpdb->options}
WHERE option_name LIKE 'plugin_%'
OR option_name LIKE '%_options'
");
foreach ($plugin_options as $option) {
if (strpos($option->option_value, $old_url) !== false) {
$updated_value = str_replace($old_url, $new_url, $option->option_value);
$wpdb->update(
$wpdb->options,
['option_value' => $updated_value],
['option_name' => $option->option_name]
);
}
}
}
?>
Migration Automation and CI/CD Integration
Continuous Integration for WordPress Migrations
GitHub Actions Workflow for Automated Testing
name: WordPress Migration Test
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
migration-test:
runs-on: ubuntu-latest
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: wordpress_test
options: >-
--health-cmd="mysqladmin ping"
--health-interval=10s
--health-timeout=5s
--health-retries=3
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
extensions: mysqli, gd, xml, mbstring
- name: Install WordPress
run: |
curl -O https://wordpress.org/latest.tar.gz
tar -xzf latest.tar.gz
cp -r wordpress/* /var/www/html/
- name: Configure WordPress
run: |
cp wp-config-sample.php wp-config.php
sed -i "s/database_name_here/wordpress_test/" wp-config.php
sed -i "s/username_here/root/" wp-config.php
sed -i "s/password_here/password/" wp-config.php
sed -i "s/localhost/127.0.0.1/" wp-config.php
- name: Install WP-CLI
run: |
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp
- name: Run Migration Tests
run: |
wp core install --url=http://localhost --title="Test Site" --admin_user=admin --admin_password=password --admin_email=test@example.com
wp plugin install all-in-one-wp-migration --activate
# Add your migration testing scripts here
- name: Validate Migration
run: |
# Add validation scripts
wp option get siteurl
wp option get home
Automated Deployment Script
#!/bin/bash
## Automated WordPress Deployment Script
set -e
## Environment variables
ENVIRONMENT=${1:-staging}
BACKUP_DIR="/backups/wordpress"
DEPLOY_LOG="/var/log/deploy.log"
## Logging function
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$ENVIRONMENT] $1" | tee -a "$DEPLOY_LOG"
}
## Pre-deployment checks
pre_deployment_checks() {
log "Starting pre-deployment checks"
# Check if WordPress is installed
if ! wp core is-installed --path=/var/www/html; then
log "ERROR: WordPress not properly installed"
exit 1
fi
# Check database connectivity
if ! wp db check --path=/var/www/html; then
log "ERROR: Database connection failed"
exit 1
fi
# Verify required plugins are active
if ! wp plugin is-active all-in-one-wp-migration --path=/var/www/html; then
log "ERROR: Required migration plugin not active"
exit 1
fi
log "Pre-deployment checks passed"
}
## Create deployment backup
create_deployment_backup() {
log "Creating deployment backup"
local timestamp=$(date +%Y%m%d_%H%M%S)
local backup_file="$BACKUP_DIR/pre_deploy_$ENVIRONMENT_$timestamp.sql"
wp db export "$backup_file" --path=/var/www/html
# Verify backup integrity
if wp db import "$backup_file" --path=/var/www/html --dry-run; then
log "Backup created and verified: $backup_file"
else
log "ERROR: Backup creation failed"
exit 1
fi
}
## Execute migration
execute_migration() {
log "Executing WordPress migration"
# Update site URLs if needed
if [ "$ENVIRONMENT" = "production" ]; then
wp search-replace "staging.example.com" "example.com" --skip-columns=guid --path=/var/www/html
fi
# Flush all caches
wp cache flush --path=/var/www/html
# Update rewrite rules
wp rewrite flush --path=/var/www/html
log "Migration completed"
}
## Post-deployment validation
post_deployment_validation() {
log "Starting post-deployment validation"
# Check site accessibility
local site_url=$(wp option get siteurl --path=/var/www/html)
if curl -f -s "$site_url" > /dev/null; then
log "Site is accessible: $site_url"
else
log "ERROR: Site is not accessible"
exit 1
fi
# Check WordPress admin
if curl -f -s "$site_url/wp-admin/" > /dev/null; then
log "WordPress admin is accessible"
else
log "ERROR: WordPress admin is not accessible"
exit 1
fi
# Verify database integrity
if wp db check --path=/var/www/html; then
log "Database integrity verified"
else
log "ERROR: Database integrity check failed"
exit 1
fi
# Check critical plugins
local critical_plugins=("all-in-one-wp-migration" "wp-super-cache")
for plugin in "${critical_plugins[@]}"; do
if wp plugin is-active "$plugin" --path=/var/www/html; then
log "Plugin $plugin is active"
else
log "WARNING: Plugin $plugin is not active"
fi
done
log "Post-deployment validation completed"
}
## Main deployment function
main() {
log "Starting WordPress deployment for $ENVIRONMENT environment"
pre_deployment_checks
create_deployment_backup
execute_migration
post_deployment_validation
log "Deployment completed successfully"
# Send notification (optional)
if command -v slack-cli &> /dev/null; then
slack-cli send "WordPress deployment to $ENVIRONMENT completed successfully"
fi
}
## Execute main function
main
Conclusion
WordPress migration doesn’t have to be overwhelming when approached systematically. By following this comprehensive guide, preparing thoroughly, and testing diligently, you can successfully migrate your WordPress site with minimal disruption to your users and SEO performance.
Remember that preparation is key – never attempt a migration without complete backups and a clear rollback plan. Take your time, test thoroughly, and don’t hesitate to seek professional help for complex migrations.
With proper planning and execution, your WordPress migration can be a smooth process that sets your site up for future growth and success.



