Create and Manage Custom Codes

Custom Codes is where you paste third-party HTML snippets — Google Analytics, cookie banners, chat widgets, conversion pixels, custom font links — and choose where they load on every page. Each snippet gets a name, a placement (<head>, <body> Start, or </body> End), and a toggle so you can pause it without deleting it. You write it once; it renders on every public page until you turn it off. This page is the fast path from "marketing sent me a GA4 script" to "it's collecting data on every page."

One global injection point

Paste a snippet once and it renders on every public page until you turn it off. It is not a page-content tool — page HTML belongs in SG-Builder.

Three placements, in order

<head>, <body> Start, or </body> End — plus a Priority number that controls order within the same placement.

Reversible, not destructive

Inactive pauses a snippet without deleting it. Trash is a soft delete. Only Delete Permanently is final.

What is this for?

Custom Codes is SGEN's global injection point for cross-cutting snippets that need to live on every page: analytics loaders, tag managers, chat widgets, cookie banners, tracking pixels, and external font links. You write the snippet once and it renders on every public page until you turn it off. It is not a page-content tool — page HTML belongs in SG-Builder.

Scope

What this feature covers, and where the boundary sits.

Covers
The snippet lifecycle

Adding new snippets, editing existing ones, activating/deactivating, setting placement and load priority, and trashing or restoring snippets.

Out of scope
Page-specific and per-page targeting

Page-specific HTML or CSS (use SG-Builder or Custom CSS), per-page conditional injection (all active codes fire site-wide — no URL targeting), and analytics dashboards (Custom Codes injects the loader; data lives in the vendor's tool).

Field reference

Every snippet is stored with five fields.

FieldRequiredPurposeNotes
TitleYesInternal labelMin 2 chars. Visitors never see it.
Code snippetYesThe HTML to injectHead placement rejects block elements.
PlacementYesWhere in the page HTMLHead / Body Start / Body End.
PriorityNoLoad order within placement1 = first. Lower priority = loads later.
StatusYesActive / InactiveInactive = saved but not running.
Head placement is strict

A <head>-placement snippet accepts only <template data-safe="script" data-attrs=""></code>, <code><style></code>, <code><link></code>, or <code><meta></code>. Block-level tags like <code><div></code>, <code><p></code>, or <code><iframe></code> are rejected. Body Start and Body End accept all HTML.</p></div> <div class="sdp-rule-card"><div class="sdp-rule-title">Priority is scoped per placement</div><p>Priority only orders snippets that share the same placement. For example, a GA4 snippet at priority 1 in Head loads before a Meta Pixel snippet at priority 2, also in Head — but has no ordering relationship with anything in Body Start or Body End.</p></div> </div> </section> <!-- 6 · WORKED EXAMPLES --> <section class="sdp-section" id="examples"> <h3 class="sdp-h3">Worked examples</h3> <p class="sdp-section-desc">Four common snippet types, with placement and priority called out.</p> <p><strong>Example 1: Google Analytics 4 measurement tag.</strong> Marketing hands you the GA4 snippet from <code>Admin → Data Streams</code>. You paste it into a new Custom Code with placement <code></body> — End</code> and activate it. On the next public-page reload, the <code>gtag</code> loader fires and starts recording sessions. Here is a sanitised version you can paste as-is after swapping the measurement ID:</p> <pre><code class="language-html"><!-- Google tag (gtag.js) --> <script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></template> <template data-safe="script" data-attrs=""> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-XXXXXXXXXX'); </template>

Once saved, the snippet renders immediately before </body> on every public page. Open your public homepage, right-click → View page source, and you will find this block near the bottom of the HTML. To confirm the tag is firing, open your site in a private/incognito window, sign in to Google Analytics, and check the Realtime report — your own visit should appear within a minute. If you use a consent banner, accept cookies first; a declined banner suppresses the tag on purpose.

Example 2: Cookie consent banner. Your cookie platform (Cookiebot, OneTrust, Osano) gives you a <template data-safe="script" data-attrs=""></code> tag plus an optional <code><style></code> block to tune the banner position. Paste both into a single Custom Code, placement <code><head></code> (so the banner renders on first paint, before any tracking code fires). Here is a Cookiebot-shaped example:</p> <pre><code class="language-html"><script id="Cookiebot" src="https://consent.cookiebot.com/uc.js" data-cbid="00000000-0000-0000-0000-000000000000" data-blockingmode="auto" type="text/javascript"></template> <template data-safe="style" data-attrs="">#CybotCookiebotDialog { font-family: inherit !important; }</template>

After saving and activating, reload the public homepage in an incognito window. The consent banner overlays on first load; clicking Allow or Decline writes the cookie and the banner disappears on subsequent loads.

Example 3: Custom font from Google Fonts. Need a specific font not in the Theme Editor? Paste the Google Fonts <link> plus a <template data-safe="style" data-attrs=""></code> override, placement <code><head></code>:</p> <pre><code class="language-html"><link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet"> <style> body { font-family: 'Inter', system-ui, sans-serif; } </template>

On the next public-page reload, typography switches to Inter site-wide. If the change does not appear immediately, hard-reload with Ctrl+Shift+R to bypass the browser cache.

Example 4: Page-scoped CSS override. You need to hide the default page subtitle on a landing page, but only on that one page — not site-wide. In SG-Builder, every page gets a unique body class based on its ID (for example, body.page_id-N, where N is the page's numeric ID). Use that body class to scope your CSS so it never leaks to other pages.

/* Page-scoped CSS override — one landing page only */
body.page_id-N /* replace N with actual page ID */ .page-subtitle { display: none;
}
body.page_id-N /* replace N with actual page ID */ .hero-section { background-color: #1a0a00; color: #f5e6d0;
}

Paste this into a new Custom Code, placement <head>, title "Landing page overrides", Status Active. The rules only fire when body.page_id-N is present — every other page is unaffected.

Why scope to a body class? Bare selectors like .page-subtitle { display: none; } hide that element on every page of your site. Always prefix with the body class for page-specific rules. If you see bare selectors in old Custom Codes, replace them with scoped versions before adding new ones.

What NOT to use this for

Six patterns that either fail on save or cause hard-to-diagnose problems later.

Don't put body-only HTML in a head-placement code

If your snippet contains <div>, <span>, <p>, <img>, <iframe>, <form>, <button>, or other body elements, SGEN rejects the save with a red error banner. Those tags belong in <body> — Start or </body> — End placements. A <head> snippet should contain only <script>, <style>, <link>, or <meta>.

Don't rely on HTML comments to mark body-placement snippets

<!-- Begin GTM container --> saves to the database, but SGEN strips comments from body-placement snippets at render time — they will not appear in public page source. If you need a visible marker, use a unique JavaScript variable (for example window.__my_tag = true;) or a data-* attribute on a wrapper <div> instead.

Don't use Custom Codes for large page content

If you are pasting a pricing table, a hero section, or a testimonial block, use SG-Builder on the page itself. Custom Codes is for cross-cutting scripts and tiny inline overrides, not copy.

Don't use it for site-wide CSS

Use Custom → CSS instead. CSS pasted here as <style> emits inline on every page, which is harder to cache and slower than the dedicated Custom CSS area.

Don't paste secrets

API keys, webhook tokens, private service URLs — whatever you paste renders verbatim in the public page source. Anyone who views source can read it. Tracking IDs (like GA4 G-XXXXXXXXXX) are fine; private keys are not.

Don't trust the "deleted" confirmation on its own

If you are scripting a delete or using the per-row Trash link, reload the list to verify the row moved to Trash — the confirmation toast alone is not proof.

How this connects to other features

Custom Codes is one of several places you can inject markup. Here is how to pick the right one.

For site-wide stylesheets, use the dedicated Custom CSS area instead. CSS pasted into Custom Codes as inline <style> ships on every page request and skips the cache layer that Custom CSS uses. Rule of thumb: CSS in Custom CSS, scripts and HTML in Custom Codes.

SG-Builder Custom HTML block

For snippets that should appear on a single page only (a hero embed, a per-page schema block, a one-off form). Custom Codes is global; the Custom HTML block is local to that page. Custom Codes has no per-page scoping today.

Page Settings → Header Scripts

That page-level field accepts <script> tags only. <style> blocks pasted there are stripped by the SGEN sanitizer. If a tag manager fragment needs a sibling stylesheet, paste both into Custom Codes instead.

Appearance → Theme Editor + Site Settings

For typography, brand colors, header/footer markup, and other chrome edits, prefer the Theme Editor. It is faster, safer, and survives platform upgrades. Custom Codes is the escape hatch when the Theme Editor cannot reach the surface you need.

Media library "Used In" tracking

When you reference a media URL inside a Custom Codes snippet (for example a banner script that loads an uploaded image), SGEN scans the snippet on save and tags the media item as "Used in Custom Codes" in the Media library. Useful before deleting media that may still be referenced from a script.

The management surface for Custom CSS uses the same list pattern (status pills, bulk actions, Trash/Restore) as Custom Codes. If you know one, you know the other.

Before you start

Confirm these before adding a snippet.

Admin access with Custom Codes permission

You are signed in to SGEN as an admin with Custom Codes access.

Know your placement

You have the snippet to paste, and you know which of the three placements it needs: <head>, <body> — Start, or </body> — End.

Safe to run on every page

Your snippet is safe to render on every public page. Custom Codes is site-wide — there is no per-page scoping today.

Per-page? Use SG-Builder instead

If you need per-page injection, use SG-Builder's Custom HTML component on the page itself.

Where to go

Three clicks from the admin home.

1
Open the left navigation

Expand the left-side menu if it is collapsed.

2
Select Custom → Codes

This opens the list of saved snippets at /sg-admin/custom_codes/.

3
Add New, or edit an existing row

Click + Add New (top-right) to create a new snippet, or click an existing row's title to edit it.

The list shows four status pills at the top (All / Active / Inactive / Trash) with live counts, a search box, a bulk-actions dropdown, and a row per saved snippet. Each row has Edit and Trash hover actions. The Placement column shows which of the three positions the snippet lives at; the Priority column controls order when multiple snippets share a placement (lower = earlier).

Steps: add a snippet

1
Open the Add New form

Click + Add New on the list toolbar. SGEN opens the Add New form under Custom → Codes → New.

2
Fill in the form

Give the snippet a descriptive Title (this is for your reference — it never appears on the public site). Paste the snippet body into the Code snippet editor. Choose the Placement that matches the vendor's instructions. Set Priority if order matters (lower = earlier). Toggle Status to Active when you are ready for it to render on the public site.

Placement quick reference: <head> is for loader scripts, fonts, and metadata. <body> — Start is for first-paint scripts like GTM pixels. </body> — End is for late-binding widgets and anything you don't want to block page paint.

3
Save the snippet

Click Create a Code. If everything is valid, SGEN saves the row, redirects you to the edit view, and flashes a green success message reading "A code has been successfully created! It is now active on every public page." The snippet begins rendering on the public site on the very next page load — there is no deploy step.

If the save fails with a red error banner: you probably put body-only HTML in a <head>-placement code. SGEN rejects the save and preserves your input in the form so you can fix it. The message reads: "Head placement cannot include body-only HTML elements like <div>, <p>, <form>, etc. Your snippet was not saved. Move the snippet to <body> — Start or </body> — End placement, or remove the body-only tags." Switch the Placement dropdown and click Create a Code again.
4
Verify on the public site

Open your public homepage in a new tab. Right-click → View page source. Search the source for a string unique to your snippet (for example the GA4 measurement ID G-XXXXXXXXXX). You should find it in the expected placement:

  • <head> — between <head> and </head>.
  • <body> — Start — immediately after the opening <body> tag.
  • </body> — End — immediately before the closing </body> tag.

For analytics, also check the vendor's own dashboard: Google Analytics Realtime, Tag Manager Preview, or Cookiebot's Scanning history. If your visit shows up there within a minute of loading the public site, the snippet is live.

5
Edit or disable later

Click a row's title (or its Edit hover action) to re-open the form with the stored values pre-filled. You can change the body, swap the placement, re-prioritise, or toggle Status to Inactive to stop it rendering without deleting the row. The edit form's sidebar also shows who authored the snippet and when it was created and last modified.

6
Trash, restore, or permanently delete

On the list view, hover a row and click Trash. The row moves to the Trash tab, still in the database but no longer rendering on the public site. On the Trash tab, each row shows three hover actions: Edit / Restore / Delete Permanently. Restore brings the row back as Inactive (not re-activated automatically — you have to flip the switch explicitly). Delete Permanently opens a confirmation modal ("Are you sure? This will permanently delete the code. You won't be able to revert this!") — confirming permanently removes the row from the database. There is no undo.

The complete flow: a new analytics setup in one session

For a new analytics setup in one session:

1
Custom → Codes → + Add New

Title "GA4 measurement tag", paste the gtag snippet, placement </body> — End, priority 1, Status Active.

2
Create a Code

Confirm the green success flash.

3
Add a second snippet for Cookiebot

Title "Cookiebot consent", placement <head>, priority 1, Status Active.

4
Open the public homepage in incognito

Banner overlays on first load, gtag starts collecting after consent.

5
View page source

The Cookiebot script is in <head>; the GA4 script is before </body>.

6
Vendor dashboards

In Google Analytics Realtime and Cookiebot Scanning, confirm your own visit appears within a minute.

What success looks like

List shows the new snippet

The list shows your new snippet with a green Active pill and your chosen Placement and Priority.

View-source confirms placement

The public homepage view-source contains the exact snippet you pasted, in the exact position you specified.

Vendor dashboard confirms tracking

For analytics tags: the vendor's Realtime/dashboard view shows your own visit appearing within a minute of loading the public site.

Consent banner behaves correctly

For consent banners: the banner appears on first visit in incognito, and is dismissed correctly.

Troubleshooting

Common issues and their fixes.

Save error
Clicked Create a Code and got a red error banner

Body-only HTML in a head-placement snippet is rejected. Switch Placement to <body> — Start or </body> — End.

Status
Snippet saved but not showing on the public site

Check Status — Inactive rows are saved but not rendered. Flip the Status switch to Active and save again, then hard-reload the public page (Ctrl+Shift+R).

Caching
Public page still shows the old version of my snippet

Caches can delay propagation. Wait 60 seconds and hard-reload; if it still lags, check with your site admin about CDN caching.

Comments
My HTML comment disappeared from the public page

Comments in body-placement snippets are stripped at render time. Put the marker inside a <script> block or a data-* attribute on a wrapper <div> instead.

Tracking
The GA collect / Cookiebot call doesn't fire

Check the vendor's measurement ID in the snippet is correct. Confirm your browser isn't running an ad-blocker that kills the vendor domain.

Trash
My snippet stopped working

Check the Trash tab — someone may have moved it there. Restore it (lands as Inactive), then flip Status to Active.

Heads up — Custom Codes has no per-page scoping: every Active snippet fires on every public page. If you need a snippet on one page only, use the Custom HTML block in SG-Builder on that page instead.

What to do next