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."
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.
<head>, <body> Start, or </body> End — plus a Priority number that controls order within the same placement.
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.
Adding new snippets, editing existing ones, activating/deactivating, setting placement and load priority, and trashing or restoring snippets.
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.
| Field | Required | Purpose | Notes |
|---|---|---|---|
| Title | Yes | Internal label | Min 2 chars. Visitors never see it. |
| Code snippet | Yes | The HTML to inject | Head placement rejects block elements. |
| Placement | Yes | Where in the page HTML | Head / Body Start / Body End. |
| Priority | No | Load order within placement | 1 = first. Lower priority = loads later. |
| Status | Yes | Active / Inactive | Inactive = saved but not running. |
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.
.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.
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>.
<!-- 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.
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.
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.
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.
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.
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.
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.
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.
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.
You are signed in to SGEN as an admin with Custom Codes access.
You have the snippet to paste, and you know which of the three placements it needs: <head>, <body> — Start, or </body> — End.
Your snippet is safe to render on every public page. Custom Codes is site-wide — there is no per-page scoping today.
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.
Expand the left-side menu if it is collapsed.
This opens the list of saved snippets at /sg-admin/custom_codes/.
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
Click + Add New on the list toolbar. SGEN opens the Add New form under Custom → Codes → New.
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.
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.
<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.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.
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.
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:
Title "GA4 measurement tag", paste the gtag snippet, placement </body> — End, priority 1, Status Active.
Confirm the green success flash.
Title "Cookiebot consent", placement <head>, priority 1, Status Active.
Banner overlays on first load, gtag starts collecting after consent.
The Cookiebot script is in <head>; the GA4 script is before </body>.
In Google Analytics Realtime and Cookiebot Scanning, confirm your own visit appears within a minute.
What success looks like
The list shows your new snippet with a green Active pill and your chosen Placement and Priority.
The public homepage view-source contains the exact snippet you pasted, in the exact position you specified.
For analytics tags: the vendor's Realtime/dashboard view shows your own visit appearing within a minute of loading the public site.
For consent banners: the banner appears on first visit in incognito, and is dismissed correctly.
Troubleshooting
Common issues and their fixes.
Body-only HTML in a head-placement snippet is rejected. Switch Placement to <body> — Start or </body> — End.
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).
Caches can delay propagation. Wait 60 seconds and hard-reload; if it still lags, check with your site admin about CDN caching.
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.
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.
Check the Trash tab — someone may have moved it there. Restore it (lands as Inactive), then flip Status to Active.
