Redirecting off-campers.com to vanever.com
How we handled our domain migration to preserve organic traffic, with automated checks verifying redirects for 240+ URLs.
At the beginning of 2025, Vanever acquired Off Campers, including a small part of the team, the website, and the proprietary software developed over the years.
Immediately after the takeover, we had two websites running on different booking systems. We quickly realized we needed to consolidate them in order to reduce complexity and provide a unified user experience. Within a few weeks, we relaunched the Vanever website on the Off Campers backend system and applied the distinctive “Off” brand design.
We updated our internal tools to be multi-tenant, allowing us to maintain a single codebase where changes applied to both websites. However, we still had to manage two separate Content Management Systems, which created extra work, especially for the marketing team.
#Why the redirect?
Mid-year, we reevaluated the need for two websites. Since off-campers.com was generating few organic bookings, we decided to sunset the domain and redirect traffic to vanever.com. This consolidation should minimize maintenance costs and strengthen the Vanever brand.
#Planning the redirect
With help from an external provider, the marketing team created a comprehensive spreadsheet, prioritizing all Off Campers pages. Obsolete or unnecessary pages were filtered out, and the remaining URLs were mapped to their new counterparts on the Vanever site. We also took the opportunity to simplify long, complicated URL slugs. For example, /blog/showering-while-camping-possibilities-sustainability-and-co became /blog/showering-while-camping.
Once the list of nearly 240 URLs was finalized, it was up to us to implement the redirects.
#The redirect
#Testing the URLs
Before implementing the redirects, we wanted to ensure all target URLs were reachable. During a code review, a coworker suggested verifying the URLs with a HEAD request to catch any 404 errors.
Using the following script, we identified about 15 broken URLs and sent them back to marketing for review:
import { appendFile } from "node:fs/promises";
import germanSites from "./german-sites.json";
import englishSites from "./english-sites.json";
for (const site of new Set([...germanSites, ...englishSites])) {
const response = await fetch(site, { method: "HEAD" });
if (!response.ok) {
console.error(`Response not okay: ${site}`);
await appendFile("not-found.txt", `${site}\n`);
} else {
console.log(`${site} is reachable.`);
}
}
#Implementing the redirect list
Using the redirect list, we applied a simple formula to format the redirects, allowing us to copy them directly from the spreadsheet into our Caddyfile. This is the configuration file for Caddy which we use as our web server.
Here is what a single redirect looks like:
redir /de/b2b-events https://vanever.com/de/kooperationen 301
#Configuring dynamic pages
We also had to handle dynamic pages, specifically for booking adjustments. These pages are generated with a random token and needed to be redirected to the new domain while preserving the exact URL structure.
@booking_adjustment {
path_regexp ^\/(en|de)\/booking-adjustment($|\/)
}
redir @booking_adjustment https://vanever.com{uri}
For example, a request to https://off-campers.com/en/booking-adjustment/abc123 would be redirected to https://vanever.com/en/booking-adjustment/abc123.
{uri} is a Caddy placeholder that represents the entire original request
URI, including the path and query string. This ensures that when redirecting,
the full structure of the original URL is preserved in the new location.
#Deploying the changes
After adding the redirects to the Caddyfile, we deployed the changes to production and manually tested a few to ensure everything was working as expected.
#The “Unindexed” Problem
Because of how we duplicated the CMS in the beginning of the year, we knew many pages were set to “noindex” in the Vanever CMS. To catch these, we wrote a script to identify unindexed pages after the migration.
We iterated through our list of German and English URLs, checking for the noindex meta tag.
We could have checked this in the CMS, but given the variety of page types and collections, we found a script was more efficient.
import { appendFile } from "node:fs/promises";
import germanSites from "./german-sites.json";
import englishSites from "./english-sites.json";
for (const site of new Set([...germanSites, ...englishSites])) {
const siteURL = new URL(site);
const response = await fetch(siteURL);
if (!response.ok) {
console.error(`Response not okay: ${site}`);
await appendFile("error.txt", `${site}\n`);
}
const body = await response.text();
const headTag = body.substring(
body.indexOf("<head>"),
body.indexOf("</head>"),
);
if (headTag.includes(`<meta name="robots" content="noindex"/>`)) {
await appendFile("non-indexed.txt", `${site}\n`);
}
}
We found a few pages that required manual adjustment and enabled indexing for them.
#Telling Google
All that remained was to inform Google about the redirect. This was easily done using the “Change of Address” tool, which is part of Google Search Console.
#Results
After several weeks of monitoring the redirect, we observed a significant increase in organic traffic to Vanever and a corresponding drop in traffic to Off Campers, indicating that the redirect was successful.