> For the complete documentation index, see [llms.txt](https://docs.themeupstudio.com/crimson/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.themeupstudio.com/crimson/getting-started/code-injection-variables.md).

# Code Injection Variables

### Code Injection variables — what they do and how to use them

These variables are read by Crimson at runtime to decide **how your site behaves** (external links, image light-box, header behavior, theme mode, pagination, contact/social visibility, etc.).

You can change them anytime from **Ghost Admin → Settings → Advanced → Code Injection → Site Header**, then *Change the variable value*, click **Save** and refresh your site.

{% hint style="info" %}
Adding these variables is already explained in the previous section - [Code Injection](/crimson/getting-started/code-injection.md).
{% endhint %}

#### How to edit safely?

1. Change **one variable at a time**.
2. Save in Ghost Admin.
3. Hard refresh your site (Ctrl/Cmd + Shift + R).
4. If required, clear your cache.
5. Confirm the change worked, then move to the next variable.

***

### Code injection variables explained

<table data-full-width="false"><thead><tr><th>Variable</th><th>What it controls</th><th>Allowed values</th><th width="100">Default</th></tr></thead><tbody><tr><td><code>GHOST_CONTENT_API_KEY</code></td><td>Features that depend on fetching posts/tags/authors will work properly. If missing/invalid, pagination on Authors and Tags pages will not work.</td><td>A valid Content API key string</td><td>-</td></tr><tr><td><code>GHOST_API_URL</code><br><em>(optional)</em></td><td>Fixes API calls in special setups (Ghost(Pro) domain differences, staging domains, etc.). If set wrong, API calls can fail.</td><td>Full URL string</td><td>-</td></tr><tr><td><code>OPEN_LINKS_IN_NEW_TAB</code></td><td>Opens external links in a new browser tab.<br><br><code>true</code><strong>:</strong> external links open in a new tab. <br><code>false</code><strong>:</strong> open in the same tab.</td><td><code>true</code> / <code>false</code></td><td><code>true</code></td></tr><tr><td><code>ENABLE_IMAGE_LIGHTBOX</code></td><td>Enables click-to-zoom <strong>image light-box</strong> popup.<br><br><code>true</code><strong>:</strong> clicking images opens a light-box.<br><code>false</code><strong>:</strong> images behave normally (no popup).</td><td><code>true</code> / <code>false</code></td><td><code>true</code></td></tr><tr><td><code>AUTO_HIDE_HEADER</code></td><td>Auto-hides the header while scrolling down, shows it when scrolling up.<br><br><code>true</code><strong>:</strong> more reading space while scrolling.<br><code>false</code><strong>:</strong> header stays visible.</td><td><code>true</code> / <code>false</code></td><td><code>true</code></td></tr><tr><td><code>DEFAULT_COLOR_SCHEME</code></td><td>Sets the site’s default color scheme selection.<br><br><code>light</code><strong>:</strong> always light.<br><code>dark</code><strong>:</strong> always dark.<br><code>system</code><strong>:</strong> matches user device setting.</td><td><code>'light'</code> / <code>'dark'</code> / <code>'system'</code></td><td><code>'system'</code></td></tr><tr><td><code>REDIRECT_ON_LOCALE</code></td><td>Redirects visitors to the site version matching their browser language (only if your site is set up for multilingual/locale routing).<br><br><code>true</code><strong>:</strong> visitors may be redirected to a language-specific version of your site.<br><code>false</code><strong>:</strong> no locale redirects.</td><td><code>true</code> / <code>false</code></td><td><code>false</code></td></tr><tr><td><code>PAGINATION_STYLE</code></td><td>How Crimson loads additional content on paginated feeds.<br><br><code>load-more</code><strong>:</strong> button loads more posts without changing page.<br><code>paginated-pages</code><strong>:</strong> classic page numbers/next page style.<br><br><em>(Authors/Tags will always use Load More)</em></td><td><code>'load-more'</code> / <code>'paginated-pages'</code></td><td><code>'load-more'</code></td></tr><tr><td><code>CONTACT_ENDPOINT</code></td><td>Shows/hides the Contact form and defines where form submissions are sent.<br><br><strong>Empty:</strong> contact form hidden.<br><strong>URL provided:</strong> contact form appears and submits to that endpoint.</td><td>URL string or empty string</td><td><code>''</code> <em>(hidden)</em></td></tr><tr><td><code>WHATSAPP_LINK</code></td><td>Shows/hides Whatsapp link on Contact page.<br><br><strong>Empty:</strong> Whatsapp row hidden.<br><strong>URL:</strong> Whatsapp row shown and points to your URL.</td><td>URL string or empty string</td><td><code>''</code> <em>(hidden)</em></td></tr><tr><td><code>USE_LOCALE_DOMAINS</code></td><td>When <code>true</code>, Crimson switches languages using mapped domains/subdomains instead of <code>/{lang}/</code> paths.</td><td><code>true</code> / <code>false</code></td><td><code>false</code></td></tr><tr><td><code>LOCALE_DOMAINS</code></td><td>Maps each language code to its target domain. Use language codes such as <code>en</code>, <code>hi</code>, <code>es</code>.</td><td><p>Valid values like</p><pre><code>{ 
 en: "englishdomain.com",
 hi: "hindidomain.com",
 es: "spanishdomain.com"
}
</code></pre></td><td><code>{}</code></td></tr><tr><td><code>LOCALE_DOMAIN_HOME_ONLY</code></td><td>When locale domains are enabled, switch to the target locale homepage instead of trying to keep the current path.</td><td><code>true</code> / <code>false</code></td><td><code>false</code></td></tr><tr><td><code>LOCALE_DOMAIN_HOME_IGNORE_PATHS</code></td><td>Comma-separated paths that should still keep their path when <code>LOCALE_DOMAIN_HOME_ONLY</code> is <code>true</code>.</td><td>String</td><td><code>''</code></td></tr></tbody></table>

{% hint style="warning" %}
If locale switching stays on the current domain, check that `LOCALE_DOMAINS` includes every language, including the main locale. Crimson falls back to the current domain when a mapping is missing.
{% endhint %}

{% hint style="info" %}
Site social accounts such as X, Facebook, LinkedIn, Bluesky, Threads, Mastodon, TikTok, YouTube, and Instagram are now managed in Ghost?s Social accounts settings, not in Code Injection.
{% endhint %}

***

### Best Practices

#### 1) Always edit in **Site Header**, not Footer

Because <code class="expression">space.vars.THEME\_NAME</code> needs the variables available **before** theme JS loads.

**Rule of thumb**

* **Variables/config** → Site Header
* **Tracking scripts** → usually OK in Header or Footer depending on provider

***

#### 2) Treat Code Injection like “configuration”

Keep it clean and minimal.

**Recommended structure**

* One `<script>` block for API vars
* One `<script>` block for `window.GLOBAL`

Avoid adding unrelated scripts in between unless you know they won’t overwrite `window.GLOBAL`.

***

#### 3) Change one thing at a time

This makes debugging easy.

**Workflow**

1. Change 1 variable
2. Save
3. Hard refresh
4. Validate visually + console

***

#### 4) Keep defaults unless you have a reason

Defaults are chosen to fit most sites:

* Open external links in a new tab (usually better UX)
* Light-box on (visual polish)
* Auto-hide header (modern reading experience)
* System theme (best for accessibility and user preference)

***

#### 5) Use correct data types (this prevents 80% of errors)

* Booleans: `true`, `false` (no quotes)
* Strings: `'system'`, `'load-more'`, URLs (quotes required)

Correct:

```javascript
AUTO_HIDE_HEADER: true,
DEFAULT_COLOR_SCHEME: 'system',
CONTACT_ENDPOINT: 'https://example.com/api/contact',
```

Incorrect:

```javascript
AUTO_HIDE_HEADER: 'true',
DEFAULT_COLOR_SCHEME: system,
CONTACT_ENDPOINT: https://example.com/api/contact,
```

***

#### 6) Use real, secure URLs for endpoints

If you enable a contact endpoint:

* Prefer `https://` .
* Ensure CORS is configured if your endpoint is on a different domain.
* Make sure your endpoint returns clear success/error responses (so you can debug easily).

**Tip:** If your endpoint is not ready yet, keep:

* `CONTACT_ENDPOINT: ''` (form stays hidden)

***

#### 7) Don’t expose Admin API keys (ever)

Only use **Content API key** in the browser. Keep Admin API keys server-side only.

***

#### 8) Version-control your “settings”

When you find a configuration you like, copy it into a safe place:

* A private Git repo / notes / password manager secure note

**Why?**

* Easy recovery if someone edits Code Injection incorrectly
* Easy migration from staging → production

***

#### 9) If something conflicts, prefer *one source of truth*

If you also have custom scripts that define `window.GLOBAL`, you can get unpredictable results.

**Best practice**

* Define `window.GLOBAL` only once in Site Header.
* If you must manipulate it later, do:

```javascript
window.GLOBAL = window.GLOBAL || {};
window.GLOBAL.AUTO_HIDE_HEADER = false;
```

***

### Troubleshooting

#### 1) “I updated variables, but nothing changed”

**Most common causes:** caching + not refreshing properly.

**Fix checklist**

1. In Ghost Admin, confirm you clicked **Save** in Code Injection.
2. Do a **hard refresh**: `Ctrl/Cmd + Shift + R`.
3. Test in an **Incognito/Private** window.
4. If you use a CDN (Cloudflare/Bunny/host caching), **purge cache**.
5. If you recently updated the theme, clear any server-level cache (if applicable).

**Quick verification**

* Right-click → **View Page Source**
* Search for: `window.GLOBAL` and `GHOST_CONTENT_API_KEY`
* If you don’t see them, they’re not being injected (wrong box, not saved, or cached HTML).

***

#### 2) “My site looks broken / white screen / header missing after adding the snippet”

This almost always happens due to a **JavaScript syntax error**.

**What to check**

* You must have:
  * matching `{` and `}`
  * matching quotes `'...'`
  * commas between properties (except after the last property)
* Don’t paste “smart quotes” from editors: use normal `'` or `"`.

**Fast debug**

1. Open DevTools → **Console**
2. Look for errors like:
   * `Uncaught SyntaxError: Unexpected token`
   * `Uncaught ReferenceError`

**Recovery tip**

* Temporarily remove the whole `window.GLOBAL` block, Save, refresh.
* Then add it back and edit **one line at a time**.

***

#### 3) “DevTools says `window.GLOBAL` is undefined”

Possible reasons:

* You pasted into **Site Footer** instead of **Site Header**
* A caching layer is serving old HTML
* Another script on your site overwrote `window.GLOBAL`

**Fix**

* Move snippet to **Site Header**, Save, hard refresh.
* In DevTools console, run:
  * `window.GLOBAL`
  * `window.GHOST_CONTENT_API_KEY`
* If `window.GLOBAL` exists but values don’t match, another script may be overwriting it. Place your snippet **as high as possible** in Site Header.

***

#### 4) “Content API features aren’t working / sections are empty”

This typically points to **API URL / key issues**.

**Symptoms**

* “Load more” doesn’t load posts
* Tag-based sections show nothing
* Console/network shows failed requests
* Authors and Tags page cannot load more authors/tags

**Fix checklist**

1. Confirm `window.GHOST_CONTENT_API_KEY` is correct (copied from the Custom Integration).
2. Check DevTools → **Network** tab:
   * Do you see requests to `/ghost/api/content/…` ?
   * Are they returning `200` or errors like `401/403/404`?
3. If requests fail due to domain mismatch, set:
   * `window.GHOST_API_URL = 'https://YOUR_API_DOMAIN'`\
     Use the **API URL/domain shown in Ghost Integration** (best source of truth).

**Common mistakes**

* Using the wrong key
* Key pasted with extra spaces/quotes accidentally
* Setting a wrong `GHOST_API_URL` domain/protocol

***

#### 5) “External links still aren’t opening in a new tab”

**Check these first**

* Is the link actually “external”? (external themes have different root domains.)
* Is your value a boolean (not a string)?
  * ✅ `OPEN_LINKS_IN_NEW_TAB: true`
  * ❌ `OPEN_LINKS_IN_NEW_TAB: 'true'`

**Test**

* Put an obvious external link in a post and re-test.

***

#### 6) “Light-box doesn’t open on images”

**Possible reasons**

* `ENABLE_IMAGE_LIGHTBOX` is `false`
* The image is wrapped in a custom HTML link that prevents the theme handler

**Fix**

* Set `ENABLE_IMAGE_LIGHTBOX: true`
* Test on a standard image inserted via the Ghost editor (not custom HTML).

***

#### 7) “Header is behaving weird / flickering / not hiding”

**Possible reasons**

* Conflicting custom scripts affecting scroll
* Very heavy pages causing scroll handler jitter
* You set `AUTO_HIDE_HEADER: true` and have a sticky announcement bar/plugin

**Fix**

* Try `AUTO_HIDE_HEADER: false` to confirm the issue is the scroll behavior.
* Remove/disable other scroll-related scripts (if any).

***

#### 8) “Color scheme isn’t respecting my setting”

**Check**

* `DEFAULT_COLOR_SCHEME` must be one of:
  * `'light'`, `'dark'`, `'system'`
* If you set `'system'`, the site will follow the OS/browser theme.

**Tip**

* Test quickly by switching your OS theme or browser theme override.

***

#### 9) “REDIRECT\_ON\_LOCALE is on, but nothing happens”

Locale redirect works only if your site is actually configured for locale-based URLs/routing.

**Fix**

* Confirm your multilingual/locale setup is implemented (routes + languages).
* If you don’t have a locale structure, keep this `false`.

***

#### 10) “Pagination style didn’t change”

**Important note**

* `PAGINATION_STYLE` only affects **post feeds** that are paginated.
* **Authors/Tags pages will always use Load More**

So if you tested on Authors/Tags pages, you may not see any change.

***

#### 11) “Contact form isn’t visible”

<code class="expression">space.vars.THEME\_NAME</code> hides the contact form when no endpoint is provided.

**Fix**

* Set a valid endpoint:
  * `CONTACT_ENDPOINT: 'https://formhandler.com/api/abc123xyz'`
* Ensure it’s `https://` and accessible publicly.
* If it still doesn’t show, check console for blocked requests or mixed content.

***

#### 12) “My social links aren’t showing on Contact page”

These are intentionally hidden when empty.

**Fix**

* Add the link as a full URL string.
* Example:
  * `LINKEDIN_LINK: 'https://linkedin.com/in/yourhandle'`
