Subchapter 2.70
references/EMBEDDED_SCRIPT.mdMarkdown10 KBView on GitHub
Embedded scripts are HTML code fragments injected into the DOM of Wix sites — for integration with third-party services, analytics tracking, advertising, and custom JavaScript functionality.
Use wix generate --params with all 5 required fields:
wix generate --params '{"extensionType":"EMBEDDED_SCRIPT","name":"<name>","folder":"<folder>","scriptType":"<scriptType>","placement":"<placement>"}'| Field | Constraint |
|---|---|
name | Display name, any string. |
folder | Lowercase alphanumeric, hyphens, slashes (for sub-paths). |
scriptType | One of: ESSENTIAL, FUNCTIONAL, ANALYTICS, ADVERTISING. |
placement | One of: HEAD, BODY_START, BODY_END. |
The CLI generates the folder, <folder>.html (the actual script HTML), the builder file, the UUID, and the src/extensions.ts registration. (It may also drop a sample <other>.ts module to demonstrate <script type="module" src="./xxx.ts"> imports — feel free to delete or repurpose it.)
After implementation, the app developer must enable SCOPE.DC-APPS.MANAGE-EMBEDDED-SCRIPTS in the Wix Dev Center — see Enable Embedded Script Permission.
Embedded scripts must declare a type for consent management:
| Type | Description | Use Cases |
|---|---|---|
ESSENTIAL | Core functionality crucial to site operation | Authentication, security features |
FUNCTIONAL | Remembers user choices to improve experience | Language preferences, UI customization |
ANALYTICS | Provides statistics on how visitors use the site | Google Analytics, Hotjar, Mixpanel |
ADVERTISING | Provides visitor data for marketing purposes | Facebook Pixel, Google Ads, retargeting |
Selection rule: If a script falls into multiple types, choose the option closest to the bottom of the list (most restrictive). For example, a script with both Analytics and Advertising aspects should be typed as ADVERTISING.
| Placement | Where in HTML | Best for |
|---|---|---|
HEAD | Between <head> and </head> tags | Analytics, tracking, early initialization |
BODY_START | Immediately after opening <body> tag | Critical functionality, <noscript> fallback |
BODY_END | Immediately before closing </body> tag | Advertising pixels, non-critical features (non-blocking, better perf) |
Every embedded script requires a companion dashboard page to configure its parameters. Scaffold a separate DASHBOARD_PAGE extension and use embeddedScripts from @wix/app-management to load/save parameters (see DASHBOARD_PAGE.md). Wix stores the parameters and injects them as {{templateVars}} into the HTML at render time.
| Type | Description | Dashboard Component |
|---|---|---|
TEXT | Single-line text | Input |
NUMBER | Numeric value | Input type=”number” |
BOOLEAN | True/false toggle | ToggleSwitch, Checkbox |
IMAGE | Image from media manager | ImagePicker |
DATE | Date only | DatePicker |
DATETIME | Date with time | DatePicker + TimeInput |
URL | URL with validation | Input |
SELECT | Dropdown options | Dropdown |
COLOR | Color value | ColorPicker |
{{parameterKey}} placeholders are substituted at injection time, but only inside HTML attribute values — not inside <script> bodies. The required pattern is: render every parameter as a data attribute on a config element, then read it from dataset in JS.
<div id="config"
data-api-key="{{apiKey}}"
data-enabled="{{enabled}}"
data-headline="{{headline}}"
></div>
<script>
const { apiKey, enabled, headline } = document.getElementById("config").dataset;
// ...
</script>Type handling (all dataset values are strings):
NUMBER → Number(value) or parseInt(value, 10)BOOLEAN → compare against "true" / "false"DATE / DATETIME → new Date(value)Other rules:
Every embedded script should have at minimum an enable/disable toggle parameter:
| Parameter | Type | Purpose |
|---|---|---|
enabled | BOOLEAN | Allow site owner to activate/disable |
apiKey | TEXT | Third-party service credentials |
trackingId | TEXT | Analytics/pixel identifiers |
headline | TEXT | Customizable display text |
color | COLOR | UI customization |
The <script type="module"> block runs at module scope, where Rollup (used by Astro) disallows return statements.
throw new Error(...) for early exits at module scope (e.g., “script disabled” / “config element not found”).async function and call it from a DOMContentLoaded listener (or directly if document.readyState !== "loading"); return is valid inside the function.See the Complete Example below for the full skeleton.
Request: “Add Google Analytics tracking to my site”
Output:
ANALYTICSHEAD{{trackingId}}Request: “Create a coupon popup that shows when cart value exceeds $50”
Output:
FUNCTIONALBODY_END{{couponCode}}, {{minimumCartValue}}, {{enablePopup}}Request: “Integrate Intercom chat widget”
Output:
FUNCTIONALBODY_END{{appId}}, {{userEmail}}, {{userName}}throw new Error() for early exits at module scope, not return. Rollup (used by Astro) doesn’t allow return statements at module scope. Wrap main logic in a named async function where return is valid.Parameters for "cart-coupon-popup":
- couponCode (TEXT, required) - The coupon code to display
- popupHeadline (TEXT, required) - Headline text
- popupDescription (TEXT, required) - Description text
- minimumCartValue (NUMBER) - Minimum cart value to show popup
- enablePopup (BOOLEAN, required) - Enable/disable toggle<div
id="popup-config"
data-coupon-code="{{couponCode}}"
data-popup-headline="{{popupHeadline}}"
data-minimum-cart-value="{{minimumCartValue}}"
data-enable-popup="{{enablePopup}}"
></div>
<div id="popup-container"></div>
<script type="module">
// Get configuration from data attributes
const config = document.getElementById("popup-config");
if (!config) throw new Error("Config element not found");
const { couponCode, popupHeadline, minimumCartValue, enablePopup } =
config.dataset;
// Exit early if disabled (use throw at module scope, not return)
if (enablePopup !== "true") {
throw new Error("Popup disabled");
}
// Main logic in a function (return is allowed here)
async function initializePopup() {
const minValue = Number(minimumCartValue) || 0;
// ... popup implementation
}
// Initialize when DOM is ready
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", initializePopup);
} else {
initializePopup();
}
</script>Uses embeddedScripts API from @wix/app-management:
import { embeddedScripts } from "@wix/app-management";
// Load parameters
const script = await embeddedScripts.getEmbeddedScript();
const params = script.parameters; // { couponCode: "...", ... }
// Save parameters (all values must be strings)
await embeddedScripts.embedScript({
parameters: {
couponCode: "SAVE20",
minimumCartValue: "50", // Number as string
enablePopup: "true", // Boolean as string
},
});After implementation, the app developer must manually enable the embedded script permission:
{app-id} with your actual app ID)SCOPE.DC-APPS.MANAGE-EMBEDDED-SCRIPTS permissionNote: This is a manual step in the Wix Dev Center. Without this permission, embedded scripts will not function on the site.