Add GeoSwap to your website in under 60 seconds
A free GeoSwap account. Create one here if you have not already.
Your Project ID, found in Foundations → Sites & script.
Access to edit your website's HTML, theme, or CMS settings.
GeoSwap works by adding a single JavaScript file to your website. This script is lightweight (under 5KB gzipped), served from a global CDN, and cached aggressively. It does not block page rendering thanks to the defer attribute.
<script>window.geoswap=window.geoswap||{q:[],track:function(){this.q.push(arguments)}};</script>
<script src="https://cdn.geoswap.co/geoswap.js" data-project="YOUR_PROJECT_ID" defer></script>The first line is a tiny queue: it lets you call geoswap.track() right away, even before the second line has finished loading. Calls made before that queue up and are sent in order once the script is ready. See Sending Conversions.
Replace YOUR_PROJECT_ID with your actual Project ID from the dashboard. The snippet on the Foundations → Sites & script page already has it filled in.
Add the script once per page. A second copy with the same Project ID is ignored, so a duplicate won't break anything, but it adds an extra download.
The script sets a few first-party cookies on your site. None of them hold personal data, and none are shared with other sites. List them in your site's privacy or cookie policy.
gs_sid counts site visits (part of usage). It holds a random ID and a timestamp, and expires after 30 minutes of inactivity. The ID never leaves the browser.gs_vid recognizes a returning visitor for unique-visitor counts. It holds a random ID and the date it was first set, and lasts up to 400 days (7 in Safari). GeoSwap stores only a one-way hash of the ID, never the ID itself.geoswap_visited_* remembers a “first visit only” redirect has run (30 days).geoswap_popup_dismissed_* and bar dismissals remember that a visitor closed a popup or bar.geoswap_consent_* stores a visitor's cookie-banner choice (Geo Consent only).geoswap_override_* is set only when someone opens an override link, and ends with the browser session.gs_s_* (local storage) holds the current visit's page count and landing campaign; gs_p_* (session storage, cleared when the tab closes) holds the previous page and time spent on it. Each page view sends the page URL, the previous page and time on it, the page count and landing campaign, and the visitor ID.Add the script tag to the <head> section of every page. If you use a shared layout or template, add it once there.
<!-- Add to your <head> section -->
<script>window.geoswap=window.geoswap||{q:[],track:function(){this.q.push(arguments)}};</script>
<script
src="https://cdn.geoswap.co/geoswap.js"
data-project="YOUR_PROJECT_ID"
defer
></script>There are three ways to add GeoSwap to WordPress, ordered from simplest to most reliable:
Install any "Insert Headers and Footers" plugin (e.g., WPCode or Insert Headers and Footers by WPBeginner). Paste the GeoSwap script into the header section.
Go to Appearance → Theme File Editor and open header.php. Add the script tag just before the closing </head> tag. Block themes don't have a header.php, so use Option A or C there.
<!-- Add before </head> in header.php -->
<script>window.geoswap=window.geoswap||{q:[],track:function(){this.q.push(arguments)}};</script>
<script
src="https://cdn.geoswap.co/geoswap.js"
data-project="YOUR_PROJECT_ID"
defer
></script>
</head>Add the following to your theme's functions.php file or a custom plugin:
function geoswap_enqueue_script() {
wp_enqueue_script(
'geoswap-geo',
'https://cdn.geoswap.co/geoswap.js',
array(),
null,
array(
'in_footer' => false, // Load in <head>
'strategy' => 'defer', // WordPress 6.3+
)
);
// Queues geoswap.track() calls made before geoswap.js loads
wp_add_inline_script('geoswap-geo', 'window.geoswap=window.geoswap||{q:[],track:function(){this.q.push(arguments)}};', 'before');
}
add_action('wp_enqueue_scripts', 'geoswap_enqueue_script');
// Add the data-project attribute
function geoswap_script_attributes($tag, $handle, $src) {
if ('geoswap-geo' !== $handle) return $tag;
return str_replace(
' src=',
' data-project="YOUR_PROJECT_ID" src=',
$tag
);
}
add_filter('script_loader_tag', 'geoswap_script_attributes', 10, 3);The easiest way is the GeoSwap Shopify app. It adds the script as a theme app embed and fills in your Project ID for you, so there's no code to edit. If you'd rather add it by hand, edit your theme:
theme.liquid (under Layout).</head> tag.<!-- Add before </head> in theme.liquid -->
<script>window.geoswap=window.geoswap||{q:[],track:function(){this.q.push(arguments)}};</script>
<script
src="https://cdn.geoswap.co/geoswap.js"
data-project="YOUR_PROJECT_ID"
defer
></script>Add the script to your root layout using the Next.js Script component:
// app/layout.tsx
import Script from "next/script";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
{children}
{/* Queues geoswap.track() calls made before geoswap.js loads */}
<script dangerouslySetInnerHTML={{ __html: "window.geoswap=window.geoswap||{q:[],track:function(){this.q.push(arguments)}};" }} />
<Script
src="https://cdn.geoswap.co/geoswap.js"
data-project="YOUR_PROJECT_ID"
strategy="afterInteractive"
/>
</body>
</html>
);
}Add the script to _app.tsx or _document.tsx:
// pages/_app.tsx
import Script from "next/script";
import type { AppProps } from "next/app";
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<Component {...pageProps} />
{/* Queues geoswap.track() calls made before geoswap.js loads */}
<script dangerouslySetInnerHTML={{ __html: "window.geoswap=window.geoswap||{q:[],track:function(){this.q.push(arguments)}};" }} />
<Script
src="https://cdn.geoswap.co/geoswap.js"
data-project="YOUR_PROJECT_ID"
strategy="afterInteractive"
/>
</>
);
}<script>window.geoswap=window.geoswap||{q:[],track:function(){this.q.push(arguments)}};</script>
<script src="https://cdn.geoswap.co/geoswap.js" data-project="YOUR_PROJECT_ID" defer></script><script>window.geoswap=window.geoswap||{q:[],track:function(){this.q.push(arguments)}};</script>
<script src="https://cdn.geoswap.co/geoswap.js" data-project="YOUR_PROJECT_ID" defer></script>Check your Squarespace plan
Code Injection isn't included on every Squarespace plan. If you don't see it under Settings → Advanced, your plan probably needs an upgrade before you can add custom scripts.
If you use Google Tag Manager, you can add GeoSwap as a custom HTML tag:
<script>window.geoswap=window.geoswap||{q:[],track:function(){this.q.push(arguments)}};</script>
<script src="https://cdn.geoswap.co/geoswap.js?p=YOUR_PROJECT_ID" defer></script>GTM removes data-* attributes
GTM's Custom HTML tag rebuilds the script element and strips data-* attributes (and defer), so data-project never survives a GTM install. Use the ?p= URL form shown above instead.
Loading GeoSwap through GTM also adds a small delay because GTM itself must load first. For the fastest geo redirects, add the script directly to your HTML head. GTM is fine for Geo Content personalization where a brief delay is acceptable.
The Verify Now button in GeoSwap reads your page's HTML, so it can't see a script that GTM adds later. That's expected. The Script Health card still turns Active once real visits come in. See the GTM guide.
After adding the script, verify it is working:
Open your website in a browser and open the browser's Developer Tools (F12 or Cmd+Option+I).
Go to the Network tab and filter by "geoswap.js". You should see the script loading successfully (HTTP 200).
Still in the Network tab, look for a decide request to edge.geoswap.co. That's the script asking the edge what to do for this visitor. If the Console shows [GeoSwap] Missing data-project attribute, the script tag is missing your Project ID.
In the GeoSwap dashboard, go to Foundations → Sites & script. The Script Health card switches to Active once real visits come in. To check right away, click Verify Now. It fetches your site's HTML and looks for the script with your Project ID.
Verify the script URL is exactly https://cdn.geoswap.co/geoswap.js. Check for typos. Ensure your HTML is valid (the script tag is properly closed).
The script tag has no data-project attribute, so it does nothing. Copy the snippet again from Foundations > Sites & script, or add data-project="YOUR_PROJECT_ID" to the tag. If a WordPress or caching plugin combines your scripts into one file, exclude geoswap.js: the script reads data-project from its own tag.
Check that the redirect is active and that its page targeting matches the page you're testing (All Pages, Specific URLs, or a URL Pattern). Then run it through Geo Tools > Simulate Rules. Changes can take about a minute to reach the edge, and a browser tab that already loaded your site may keep the previous decision for up to 5 minutes, so test in a new private window.
Add the geoswap-hide class to the elements GeoSwap swaps. The script hides them as soon as it runs and shows them again once the content is in place. See the anti-flicker section below.
Some aggressive ad blockers block third-party scripts. When that happens the visitor simply sees your original page. Nothing breaks, but no geo rules apply for them.
If you use Geo Content and notice a brief flash of default content before the personalized content appears, add the geoswap-hide class to the elements GeoSwap swaps:
<h1 class="hero-headline geoswap-hide">
Free shipping on every order
</h1>The script hides these elements as soon as it runs and shows them again once it has decided what this visitor should see. If the edge doesn't answer within 3 seconds, it shows them anyway, so your page is never stuck with hidden content. You don't need to add any CSS yourself.
This is optional and only relevant for Geo Content. Geo Redirects and Geo Links do not have a flicker issue because they navigate to a different page entirely.
Set up your first geo redirect rule.