{/* This file is NOT rendered directly. Sections are imported by framework pages. */}

<section id="intro">
  The script loader manages third-party scripts based on consent state. Scripts are defined in the provider's `scripts` option and are automatically loaded when their required consent category is granted, and unloaded when consent is revoked.

  c15t has a collection of premade scripts available in `@c15t/scripts`. Check the [integrations overview](/docs/integrations/overview) first before manually building a script.

  | Package manager | Command                     |
  | :-------------- | :-------------------------- |
  | npm             | `npm install @c15t/scripts` |
  | pnpm            | `pnpm add @c15t/scripts`    |
  | yarn            | `yarn add @c15t/scripts`    |
  | bun             | `bun add @c15t/scripts`     |

  > ℹ️ **Info:**
  > We recommend using the pre-built integrations when possible.
  >
  > ℹ️ **Info:**
  > If you need a vendor we do not ship yet, see the custom integration guide. It covers both one-off Script objects and reusable manifest-backed integrations.
  >
  > ℹ️ **Info:**
  > For app-specific scripts, use a plain Script object. For reusable integrations, prefer a manifest-backed helper so startup phases, consent signaling, and future server-side loading support stay structured.
</section>

<section id="script-types-to-advanced">
  ## Choose the Right Approach

  * Use a plain `Script` for one-off app code.
  * Use a manifest-backed helper in `@c15t/scripts` for reusable integrations, contributions, or anything that needs structured startup behavior.

  If you are building something reusable, start with the [custom integration guide](/docs/integrations/building-integrations) before using raw callbacks.

  ## Reusable Integrations

  For app-specific use, raw `Script` objects are usually enough.

  For reusable integrations, c15t uses a manifest-backed model in `@c15t/scripts`. That keeps startup phases, consent signaling, and vendor-specific boot logic structured instead of hidden inside large callback bodies.

  If you are building an integration for multiple apps or contributing upstream, use the [custom integration guide](/docs/integrations/building-integrations).

  ## Script Types

  ### Standard Scripts

  Load an external JavaScript file via a `<script>` tag. Use `src` to specify the URL.

  ### Inline Scripts

  Execute inline JavaScript code. Use `textContent` instead of `src`:

  ```tsx
  {
    id: 'gtag-config',
    textContent: `
      window.dataLayer = window.dataLayer || [];
      function gtag(){dataLayer.push(arguments);}
      gtag('js', new Date());
      gtag('config', 'G-XXXXXX');
    `,
    category: 'measurement',
  }
  ```

  ### Callback-Only Scripts

  Don't inject any `<script>` tag - just execute callbacks based on consent changes. Useful for controlling libraries that are already loaded:

  ```tsx
  {
    id: 'posthog-consent',
    callbackOnly: true,
    category: 'measurement',
    onLoad: ({ hasConsent }) => {
      if (hasConsent) {
        posthog.opt_in_capturing();
      }
    },
    onConsentChange: ({ hasConsent }) => {
      if (hasConsent) {
        posthog.opt_in_capturing();
      } else {
        posthog.opt_out_capturing();
      }
    },
  }
  ```

  ## Consent Conditions

  The `category` field accepts a `HasCondition` - either a simple string or a logical expression:

  ```tsx
  // Simple: requires measurement consent
  { category: 'measurement' }

  // AND: requires both measurement and marketing
  { category: { and: ['measurement', 'marketing'] } }

  // OR: requires either measurement or marketing
  { category: { or: ['measurement', 'marketing'] } }
  ```

  ## Script Callbacks

  Every script supports four lifecycle callbacks:

  | Callback          | When                                          | Use Case                 |
  | ----------------- | --------------------------------------------- | ------------------------ |
  | `onBeforeLoad`    | Before the script tag is injected             | Set up global variables  |
  | `onLoad`          | Script loaded successfully                    | Initialize the library   |
  | `onError`         | Script failed to load                         | Log error, load fallback |
  | `onConsentChange` | Consent state changed (script already loaded) | Toggle tracking on/off   |

  ```tsx
  {
    id: 'analytics',
    src: 'https://analytics.example.com/v2.js',
    category: 'measurement',
    onBeforeLoad: ({ id }) => {
      console.log(`Loading script: ${id}`);
    },
    onLoad: ({ element }) => {
      window.analytics.init('my-key');
    },
    onError: ({ error }) => {
      console.error('Failed to load analytics:', error);
    },
    onConsentChange: ({ hasConsent, consents }) => {
      window.analytics.setConsent(hasConsent);
    },
  }
  ```

  ## Advanced Options

  ### Always Load

  Scripts that manage their own consent internally (like GTM in consent mode):

  ```tsx
  {
    id: 'google-tag-manager',
    src: 'https://www.googletagmanager.com/gtm.js?id=GTM-XXXX',
    category: 'measurement',
    alwaysLoad: true, // Loads regardless of consent state
  }
  ```

  ### Persist After Revocation

  Keep the script loaded even after consent is revoked (the page won't reload for this script):

  ```tsx
  {
    id: 'error-tracking',
    src: 'https://errors.example.com/track.js',
    category: 'measurement',
    persistAfterConsentRevoked: true,
  }
  ```

  ### Script Placement

  Control where in the DOM the script is injected:

  ```tsx
  {
    id: 'widget',
    src: 'https://widget.example.com/embed.js',
    category: 'experience',
    target: 'body', // 'head' (default) or 'body'
  }
  ```

  ### Ad Blocker Evasion

  Script element IDs are anonymized by default to avoid ad blocker pattern matching:

  ```tsx
  {
    id: 'analytics',
    src: '...',
    category: 'measurement',
    anonymizeId: true, // default: true
  }
  ```
</section>

<section id="api-reference">
  ## API Reference

  | Property                   | Type                                              | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | Default |  Required  |
  | :------------------------- | :------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------ | :--------: |
  | id                         | string                                            | Unique identifier for the script                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | -       | ✅ Required |
  | src                        | string \| undefined                               | URL of the script to load                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | -       |  Optional  |
  | textContent                | string \| undefined                               | Inline JavaScript code to execute                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | -       |  Optional  |
  | category                   | HasCondition\<AllConsentNames>                    | Consent category or condition required to load this script                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | -       | ✅ Required |
  | callbackOnly               | boolean \| undefined                              | Whether this is a callback-only script that doesn't need to load an external resource.&#xA;When true, no script tag will be added to the DOM, only callbacks will be executed.&#xA;&#xA;This is useful for:&#xA;- Managing consent for libraries already loaded on the page&#xA;- Enabling/disabling tracking features based on consent changes&#xA;- Running custom code when consent status changes without loading external scripts&#xA;&#xA;Example use cases:&#xA;- Enabling/disabling Posthog tracking&#xA;- Configuring Google Analytics consent mode&#xA;- Managing cookie consent for embedded content | false   |  Optional  |
  | persistAfterConsentRevoked | boolean \| undefined                              | Whether the script should persist after consent is revoked.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | false   |  Optional  |
  | alwaysLoad                 | boolean \| undefined                              | Whether the script should always load regardless of consent state.&#xA;&#xA;This is useful for scripts like Google Tag Manager or PostHog that manage&#xA;their own consent state internally. The script will load immediately and&#xA;never be unloaded based on consent changes.&#xA;&#xA;Note: When using this option, you are responsible for ensuring the script&#xA;itself respects user consent preferences through its own consent management.                                                                                                                                                          | false   |  Optional  |
  | fetchPriority              | "high" \| "low" \| "auto" \| undefined            | Priority hint for browser resource loading                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | -       |  Optional  |
  | attributes                 | Record\<string, string> \| undefined              | Additional attributes to add to the script element                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | -       |  Optional  |
  | async                      | boolean \| undefined                              | Whether to use async loading                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | -       |  Optional  |
  | defer                      | boolean \| undefined                              | Whether to defer script loading                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | -       |  Optional  |
  | nonce                      | string \| undefined                               | Content Security Policy nonce                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | -       |  Optional  |
  | anonymizeId                | boolean \| undefined                              | Whether to use an anonymized ID for the script element, this helps ensure the script is not blocked by ad blockers                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | true    |  Optional  |
  | target                     | "head" \| "body" \| undefined                     | Where to inject the script element in the DOM.&#xA;- \`'head'\`: Scripts are appended to \`\<head>\` (default)&#xA;- \`'body'\`: Scripts are appended to \`\<body>\`&#xA;&#xA;Use \`'body'\` for scripts that:&#xA;- Need to manipulate DOM elements that don't exist until body loads&#xA;- Should load after page content for performance reasons&#xA;- Are required by third-party services to be in the body&#xA;&#xA;Use \`'head'\` (default) for scripts that:&#xA;- Need to track early page events (analytics)&#xA;- Should be available before page render&#xA;- Most tracking/analytics scripts       | 'head'  |  Optional  |
  | onBeforeLoad               | ((info: ScriptCallbackInfo) => void) \| undefined | Callback executed before the script is loaded                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | -       |  Optional  |
  | onLoad                     | ((info: ScriptCallbackInfo) => void) \| undefined | Callback executed when the script loads successfully                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | -       |  Optional  |
  | onError                    | ((info: ScriptCallbackInfo) => void) \| undefined | Callback executed if the script fails to load                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | -       |  Optional  |
  | onConsentChange            | ((info: ScriptCallbackInfo) => void) \| undefined | Callback executed whenever the consent store is changed.&#xA;This callback only applies to scripts already loaded.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | -       |  Optional  |
  | vendorId                   | string \| number \| undefined                     | IAB TCF vendor ID - links script to a registered vendor.&#xA;&#xA;When in IAB mode, the script will only load if this vendor has consent.&#xA;Takes precedence over \`category\` when in IAB mode.&#xA;Use custom vendor IDs (string or number) to gate non-IAB vendors too.                                                                                                                                                                                                                                                                                                                                    | -       |  Optional  |
  | iabPurposes                | number\[] \| undefined                            | IAB TCF purpose IDs this script requires consent for.&#xA;&#xA;When in IAB mode and no vendorId is set, the script will only load&#xA;if ALL specified purposes have consent.                                                                                                                                                                                                                                                                                                                                                                                                                                   | -       |  Optional  |
  | iabLegIntPurposes          | number\[] \| undefined                            | IAB TCF legitimate interest purpose IDs.&#xA;&#xA;These purposes can operate under legitimate interest instead of consent.&#xA;The script loads if all iabPurposes have consent OR all iabLegIntPurposes&#xA;have legitimate interest established.                                                                                                                                                                                                                                                                                                                                                              | -       |  Optional  |
  | iabSpecialFeatures         | number\[] \| undefined                            | IAB TCF special feature IDs this script requires.&#xA;&#xA;Special features require explicit opt-in:&#xA;- 1: Use precise geolocation data&#xA;- 2: Actively scan device characteristics for identification                                                                                                                                                                                                                                                                                                                                                                                                     | -       |  Optional  |
</section>
