Redirecting off-campers.com to vanever.com

4 min read

How we handled our domain migration to preserve organic traffic, with automated checks verifying redirects for 240+ URLs.

Blurry background of Post Thumbnail Post Thumbnail

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.

Spreadsheet of URLs to be redirected
Spreadsheet of URLs to be redirected

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:

index.ts
      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:

Caddyfile.prod
      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.

Caddyfile.prod
      @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.

Info

{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.

Google Search shows redirect
Google Search shows redirect

#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.

Traffic spike for https://vanever.com in Google Search Console after redirect
Traffic spike for https://vanever.com in Google Search Console after redirect