Global Scripts Module — Admin
HTTP surface for managing global scripts — raw HTML/JS snippets (analytics tags, marketing pixels, inline <style> blocks, chat widgets) that the storefront injects into one of…
HTTP surface for managing global scripts — raw HTML/JS snippets (analytics tags, marketing pixels, inline <style> blocks, chat widgets) that the storefront injects into one of three document slots at render time. Admins author, prioritise, enable/disable, and soft-delete scripts here; the storefront reads the enabled set per slot via the public surface (see ../store/global-script.md).
Source:
api-modules/global-script/src/controllers/admin-global-script.controller.ts.Content is operator-trusted raw markup injected verbatim into the storefront
<head>/<body>. There is no sanitisation — this is an admin-only authoring surface gated by RBAC, and the operator is responsible for the snippets they paste.
Conventions
Authentication
All endpoints require a Better-Auth admin session and a role granting the matching globalScript:* permission.
| Endpoint group | Permission |
|---|---|
GET /admin/global-scripts, GET /admin/global-scripts/:id | globalScript: read |
POST /admin/global-scripts | globalScript: create |
PUT /admin/global-scripts/:id, POST /admin/global-scripts/:id/restore | globalScript: update |
DELETE /admin/global-scripts/:id | globalScript: delete |
Response envelope
Successful responses are wrapped by ResponseInterceptor:
{
"data": <payload>,
"message": "Success",
"statusCode": 200,
"metadata": { /* optional, e.g. pagination */ }
}Error envelope
statusCode | errorCode examples |
|---|---|
| 400 | BAD_REQUEST, VALIDATION_ERROR |
| 401 | UNAUTHORIZED |
| 403 | FORBIDDEN |
| 404 | NOT_FOUND |
| 500 | INTERNAL_SERVER_ERROR, DATABASE_ERROR |
Lifecycle
Scripts soft-delete via deletedAt (hidden from the storefront and from default admin listings). POST /admin/global-scripts/:id/restore reverses the deletion.
Positions
A script renders in exactly one slot:
| Position | Storefront slot |
|---|---|
HEAD | inside <head> |
BODY_START | immediately after <body> opens |
BODY_END | immediately before </body> closes |
Within a slot, scripts render by priority ascending, ties broken by createdAt ascending.
Domain types
GlobalScriptResponse
type GlobalScriptPosition = "HEAD" | "BODY_START" | "BODY_END";
type GlobalScriptResponse = {
id: string;
title: string; // operator-facing label
content: string; // raw HTML/JS (verbatim)
position: GlobalScriptPosition;
priority: number; // 0..1000; lower renders first
isEnabled: boolean;
metadata: Record<string, unknown> | null;
createdAt: string; // ISO
updatedAt: string;
deletedAt: string | null;
};Endpoints
Base path: /admin/global-scripts.
GET /admin/global-scripts — List scripts
Required permission: globalScript: read. Standard QueryDto (searchValue / searchField / limit / offset / sortBy / sortDirection / filters[]) plus first-class filters.
Query
| Name | Type | Notes |
|---|---|---|
position | GlobalScriptPosition? | HEAD / BODY_START / BODY_END |
isEnabled | boolean? | Coerced from true/false |
limit, offset, searchValue, sortBy, sortDirection, filters[] | — | Standard QueryDto (limit default 100, max 500; offset default 0) |
Response 200 — paginated envelope of GlobalScriptResponse[].
GET /admin/global-scripts/:id — Get a script
Required permission: globalScript: read.
Errors
| Status | Code | When |
|---|---|---|
| 404 | NOT_FOUND | Unknown id |
POST /admin/global-scripts — Create a script
Required permission: globalScript: create.
Body
{
"title": "GA4 base tag",
"content": "<script>/* gtag snippet */</script>",
"position": "HEAD",
"priority": 0,
"isEnabled": true,
"metadata": { "vendor": "google-analytics" }
}| Field | Type | Constraints |
|---|---|---|
title | string | 1..255 chars |
content | string | 1..65536 chars (64 KB cap) |
position | enum | HEAD / BODY_START / BODY_END |
priority | int? | 0..1000. Default 0 |
isEnabled | boolean? | Default true |
metadata | Record<string, unknown> | null? | Free-form |
Response 201 — GlobalScriptResponse.
Errors
| Status | Code | When |
|---|---|---|
| 400 | VALIDATION_ERROR | Body fails zod (missing title/content, bad position, content over 64 KB, priority out of range) |
PUT /admin/global-scripts/:id — Update a script
Required permission: globalScript: update. Partial update — every field from create is optional; sent fields replace their current values.
Body — partial CreateGlobalScriptInput.
Response 200 — updated GlobalScriptResponse.
Errors
| Status | Code | When |
|---|---|---|
| 404 | NOT_FOUND | Unknown id |
| 400 | VALIDATION_ERROR | Body fails zod |
DELETE /admin/global-scripts/:id — Soft-delete
Required permission: globalScript: delete. Stamps deletedAt. Hidden from storefront and default admin listings. Reversible via POST /:id/restore.
Response 200 — the deleted GlobalScriptResponse.
Errors
| Status | Code | When |
|---|---|---|
| 404 | NOT_FOUND | Unknown id |
POST /admin/global-scripts/:id/restore — Restore
Required permission: globalScript: update. Clears deletedAt.
Response 200 — GlobalScriptResponse.
Errors
| Status | Code | When |
|---|---|---|
| 404 | NOT_FOUND | Unknown id |
Related modules
admin-rbac— gates every endpoint viaglobalScript:*permissions. Seeadmin-rbac.md.- Storefront global-scripts — consumes the enabled set per slot at render time. See
../store/global-script.md.
Free Gift Module — Admin
HTTP surface for managing free-gift rules — one row per promotion. The cart engine evaluates active rules and produces cart.pendingGifts[], which the customer resolves into an…
Google Merchant Center Module — Admin
HTTP surface for syncing eligible product variants to a Google Merchant Center account via the Merchant API v1 (the canonical successor to the deprecated Content API for…