We get it—moving dozens or even hundreds of websites can feel overwhelming. But don’t worry! With WP Umbrella, you can quickly and safely migrate all your sites from ManageWP using a simple bulk process. Follow this step-by-step guide to complete the migration and start managing everything with WP Umbrella.
Estimated Time to Complete: About 10 minutes (depending on the number of sites)
Prerequisites:
An active WP Umbrella account (Note: Trial accounts need to be upgraded for migration)
Access to your ManageWP account
WordPress Admin access for all sites
To avoid connection issues, we highly recommend whitelisting our IP addresses in any security system, firewall, or CDN you use.
Here are the IPs to whitelist:
IPv4:
212.129.45.77
212.83.142.5
212.83.175.107
IPv6:
2001:41d0:306:1702::/64
2001:BC8:2B7F:801::292/64👉 Where to whitelist:
Security plugins like WordFence
Hosting provider firewalls
CDN services like Cloudflare
📚 For more help, check out our detailed IP whitelisting guide.
Log into your ManageWP dashboard.
Use the Bulk Add Plugin feature to install and activate the WP Umbrella plugin from the WordPress.org repository on all your websites at once.

In ManageWP, select all the websites you want to migrate.
Head over to the Code Snippets tool in ManageWP—we’ll use this to run a script that connects all your websites to WP Umbrella automatically.
Copy and paste the code below into ManageWP’s code snippet feature:
<?php
// Replace WP_UMBRELLA_CLIENT_API with the customer's own WP Umbrella API key.
$wp_umbrella_api_key = 'API_KEY';
echo call_user_func(function ($apiKey) {
$site = function_exists('site_url') ? site_url() : 'unknown-site';
// ManageWP may execute snippets before WP Umbrella is loaded.
if (!function_exists('wp_umbrella_get_service')) {
$wp_umbrella_plugin = WP_PLUGIN_DIR . '/wp-health/wp-health.php';
if (file_exists($wp_umbrella_plugin)) {
require_once $wp_umbrella_plugin;
}
}
if (!function_exists('wp_umbrella_get_service')) {
return sprintf(
"[%s] FAILED plugin_not_loaded (WP Umbrella service is unavailable)\n",
$site
);
}
if ($apiKey === '' || $apiKey === 'WP_UMBRELLA' . '_CLIENT_API') {
return sprintf(
"[%s] FAILED api_key_placeholder (the API key was not replaced in the snippet)\n",
$site
);
}
$optionService = wp_umbrella_get_service('Option');
$ownerService = wp_umbrella_get_service('Owner');
$projectsService = wp_umbrella_get_service('Projects');
$contextService = wp_umbrella_get_service('WordPressContext');
$hostResolver = wp_umbrella_get_service('HostResolver');
if (!$optionService || !$ownerService || !$projectsService || !$contextService || !$hostResolver) {
return sprintf(
"[%s] FAILED container_unavailable (plugin loaded but services did not resolve)\n",
$site
);
}
if (
!function_exists('wp_umbrella_generate_random_string') ||
!function_exists('wp_umbrella_request_token_from_response')
) {
return sprintf(
"[%s] FAILED plugin_incomplete (plugin does not expose the pairing helpers)\n",
$site
);
}
$stored = $optionService->getOptions(['secure' => false]);
$storedRequestToken = $optionService->getRequestTokenWithoutCache();
$storedApiKey = $optionService->getApiKeyWithoutCache();
$storedSecretToken = $optionService->getSecretTokenWithoutCache();
$storedProjectId = isset($stored['project_id']) ? $stored['project_id'] : '';
// A site connected through the current pairing carries a request token.
if (!empty($storedRequestToken)) {
$shown = $storedProjectId !== '' ? $storedProjectId : 'unknown';
return sprintf(
"[%s] SKIPPED already_connected (project_id=%s, nothing changed)\n",
$site,
$shown
);
}
// An api_key sitting next to a secret token or a project is a working
// legacy connection, not an unfinished attempt. Those keep running without
// a request token, so they are left strictly alone.
if (!empty($storedApiKey) && (!empty($storedSecretToken) || $storedProjectId !== '')) {
$shown = $storedProjectId !== '' ? $storedProjectId : 'unknown';
return sprintf(
"[%s] SKIPPED legacy_connected (project_id=%s, nothing changed)\n",
$site,
$shown
);
}
// What is left is an api_key on its own: an attempt that never completed.
// It is only ours to resume when the key matches.
if (!empty($storedApiKey) && $storedApiKey !== $apiKey) {
return sprintf(
"[%s] SKIPPED other_account (the site holds a different API key, nothing changed)\n",
$site
);
}
$me = $ownerService->validateApiKeyOnApplication(['api_key' => $apiKey]);
if (!is_array($me)) {
return sprintf(
"[%s] FAILED api_unreachable (no answer from the WP Umbrella API)\n",
$site
);
}
if (isset($me['code'])) {
return sprintf(
"[%s] FAILED api_key_invalid (%s)\n",
$site,
$me['code']
);
}
if (!isset($me['result']) || !is_array($me['result'])) {
return sprintf(
"[%s] FAILED unexpected_me_response (no result field)\n",
$site
);
}
$owner = $me['result'];
$projectId = isset($owner['project']['id']) ? $owner['project']['id'] : null;
// The quota is a limit on creating projects. Reattaching an existing one
// adds nothing to the account, so a full account can still be repaired.
if (
$projectId === null &&
isset($owner['total_projects'], $owner['limit_projects']) &&
$owner['total_projects'] >= $owner['limit_projects']
) {
return sprintf(
"[%s] FAILED limit_exceeded (%s of %s sites used on this account)\n",
$site,
$owner['total_projects'],
$owner['limit_projects']
);
}
$workspaceCount = isset($owner['workspaces']) && is_array($owner['workspaces'])
? count($owner['workspaces'])
: 0;
$workspaceNote = $workspaceCount > 1
? sprintf(
' WARNING: %d workspaces reachable with this key, the site lands in the one the key belongs to.',
$workspaceCount
)
: '';
// The three signing fields are handled inline rather than through the
// plugin service that owns them, which is not present on every version
// this snippet has to run on.
$clearSigningKey = function ($options) {
$options['public_key'] = '';
$options['key_id'] = '';
$options['key_state'] = '';
return $options;
};
$applySigningKey = function ($options, $signingKey) {
if (
!is_array($signingKey) ||
!isset($signingKey['public_key'], $signingKey['key_id'])
) {
return $options;
}
$existing = isset($options['public_key'])
? $options['public_key']
: '';
$hasExisting = is_string($existing) && $existing !== '';
if ($hasExisting && $existing !== $signingKey['public_key']) {
return $options;
}
$options['public_key'] = $signingKey['public_key'];
$options['key_id'] = $signingKey['key_id'];
if (
!$hasExisting ||
!isset($options['key_state']) ||
$options['key_state'] !== 'new'
) {
$options['key_state'] = 'dual';
}
return $options;
};
$readSigningKey = function ($response) {
if (!function_exists('wp_umbrella_signing_key_from_response')) {
return null;
}
return wp_umbrella_signing_key_from_response($response);
};
$secretToken = wp_umbrella_generate_random_string(128);
$wasNewHash = wp_umbrella_is_new_hash();
if (!$wasNewHash) {
wp_umbrella_init_new_hash();
}
// Everything below can fail on a site we do not control, so the state we
// found is put back as it was rather than blanked.
$restore = function () use ($optionService, $stored, $wasNewHash) {
$optionService->setOptions($stored);
if (
!$wasNewHash &&
function_exists('wp_umbrella_rollback_new_hash')
) {
wp_umbrella_rollback_new_hash();
}
wp_cache_flush();
wp_load_alloptions(true);
};
$options = $stored;
$options['allowed'] = true;
$options['api_key'] = $apiKey;
$options['secret_token'] = $contextService->getHash($secretToken);
$options['project_id'] = $projectId;
$options['request_token'] = '';
$options = $clearSigningKey($options);
$optionService->setOptions($options);
wp_cache_flush();
wp_load_alloptions(true);
try {
if ($projectId !== null) {
$response = $projectsService->validateSecretToken([
'base_url' => site_url(),
'rest_url' => rest_url(),
'secret_token' => $secretToken,
'http_auth_user' => null,
'http_auth_password' => null,
'save' => true,
], $apiKey);
if (!is_array($response) || !isset($response['success'])) {
$restore();
return sprintf(
"[%s] FAILED api_unreachable (validation-secret-token gave no answer)\n",
$site
);
}
if (!$response['success']) {
$code = isset($response['data']['code'])
? $response['data']['code']
: (
isset($response['code'])
? $response['code']
: 'failed_authorize_wordpress'
);
$restore();
return sprintf(
"[%s] FAILED reattach_refused (%s, project_id=%s)\n",
$site,
$code,
$projectId
);
}
$requestToken = wp_umbrella_request_token_from_response($response);
if ($requestToken) {
$options['request_token'] = $requestToken;
$options['api_key'] = '';
}
$options = $applySigningKey(
$options,
$readSigningKey($response)
);
$optionService->setOptions($options);
return sprintf(
"[%s] SUCCESS reattached to existing project_id=%s%s\n",
$site,
$projectId,
$workspaceNote
);
}
$contextService->requireWpRewrite();
$name = get_bloginfo('name');
$response = $projectsService->createProjectOnApplication([
'base_url' => site_url(),
'home_url' => home_url(),
'rest_url' => rest_url(),
'backdoor_url' => plugins_url(),
'admin_url' => get_admin_url(),
'wp_umbrella_url' => WP_UMBRELLA_DIRURL,
'secret_token' => $secretToken,
'is_multisite' => is_multisite(),
'name' => empty($name) ? site_url() : $name,
'hosting' => $hostResolver->getCurrentHost(),
], $apiKey);
if (!is_array($response)) {
$restore();
return sprintf(
"[%s] FAILED api_unreachable (project creation gave no answer)\n",
$site
);
}
$newProjectId = isset($response['result']['id'])
? $response['result']['id']
: null;
$created =
isset($response['success']) &&
$response['success'] === 'success' &&
$newProjectId !== null;
if (!$created) {
$code = isset($response['code'])
? $response['code']
: 'failed_create_project';
$restore();
return sprintf(
"[%s] FAILED create_project (%s)\n",
$site,
$code
);
}
$result = is_array($response['result'])
? $response['result']
: [];
$options['project_id'] = $newProjectId;
$requestToken = wp_umbrella_request_token_from_response($result);
if ($requestToken) {
$options['request_token'] = $requestToken;
$options['api_key'] = '';
}
$options = $applySigningKey(
$options,
$readSigningKey($result)
);
$optionService->setOptions($options);
update_option('wp_umbrella_backup_version', 'v4', false);
return sprintf(
"[%s] SUCCESS connected as new project_id=%s%s\n",
$site,
$newProjectId,
$workspaceNote
);
} catch (\Exception $e) {
$restore();
return sprintf(
"[%s] FAILED unexpected_error (%s)\n",
$site,
$e->getMessage()
);
}
}, $wp_umbrella_api_key);🔑 Important:
Replace 'API_KEY' with your actual WP Umbrella API key.
Run this script only once to avoid delays caused by ManageWP’s cron jobs.
Once the migration is done, reach out to our team, and we’ll help you set up and review your first set of backups to ensure everything runs smoothly.
1. What if I don’t whitelist the IPs?
Your sites may block WP Umbrella connections, causing sync issues. Whitelisting is optional but highly recommended to prevent this.
2. Can I use this method with a trial WP Umbrella account?
No, you need a full account to complete the migration. Contact us if you need help upgrading.
3. What if I don’t see all my websites listed in ManageWP?
First, make sure all sites are added and connected properly in ManageWP.
4. The code snippet gives an error. What now?
Double-check that you replaced 'API_KEY' correctly and that the WP Umbrella plugin is installed on all sites. If the error persists, contact our support.
5. Can I get help with this migration?
Absolutely! Fill out this migration form and we’ll get back to you.
You've now successfully set up WP Umbrella across all your sites—fast and easy! 🚀
If you need help migrating or prefer us to handle it, we offer a free migration service that includes:
Full site transfers
Tags and client transfers
👉 Fill out this migration form, and our team will get back to you quickly!
Welcome to WP Umbrella! 🌐💙