---
title: "Registry Scripts · Nuxt Scripts"
meta:
  description: "Nuxt Scripts lets you load third-party scripts with better performance, privacy, security and DX. It includes many popular third-parties out of the box."
  "og:description": "Nuxt Scripts lets you load third-party scripts with better performance, privacy, security and DX. It includes many popular third-parties out of the box."
  "og:title": "Registry Scripts · Nuxt Scripts"
---

```

Nuxt Scripts on GitHub

**

**Guides**

# **Registry Scripts**

[Copy for LLMs](https://scripts.nuxt.com/docs/v0/guides/registry-scripts.md)

Registry scripts enhance the developer experience by simplifying the integration of third-party scripts in Nuxt Scripts.

For the list of supported registry scripts, see the [**~~Script Registry~~**](https://scripts.nuxt.com/scripts) list.

## Features

### 😌 Safe Initialization

Many third-party scripts require initialing some global state before loading the script, Nuxt Scripts handles this for you in an optimized way.

### 🏎️ Fine-grain performance tuning

Each registry script has been optimized to load the script functionality in the most efficient way possible.

### 📜 Fully Typed

Handling third-party scripts usually means dealing with their API types on your own. Registry scripts alleviate this by providing predefined types, enabling code completion and type safety in your projects.

### ✅ Validating Options

Using [**~~Valibot~~**](https://github.com/fabian-hiller/valibot), registry scripts automatically validate the configuration options of third-party scripts, helping you identify and resolve misconfigurations early. For instance, they check the token length for Cloudflare Web Analytics.

```
export const CloudflareWebAnalyticsOptions = object({
  /**
   * The Cloudflare Web Analytics token.
   */
  token: string([minLength(32)]),
  /**
   * Cloudflare Web Analytics enables measuring SPAs automatically by overriding the History API’s pushState function
   * and listening to the onpopstate. Hash-based router is not supported.
   *
   * @default true
   */
  spa: optional(boolean()),
})
``````
useScriptCloudflareWebAnalytics({
  token: '123', // will throw an error, string is not 32 chars
})
``` For performance reasons, validation will only occur during development. It will be tree-shaken out of your production build. ### 🤫 Runtime Config Integration Registry scripts can be configured through your `.env` file, allowing you to provide script options without hardcoding them in your codebase.```
NUXT_PUBLIC_SCRIPTS_CLOUDFLARE_WEB_ANALYTICS_TOKEN=YOUR_TOKEN
``````
export default defineNuxtConfig({
  scripts: {
    registry: {
      // loads the script
      cloudflareWebAnalytics: true,
    },
  },
  runtimeConfig: {
    public: {
      scripts: {
        cloudflareWebAnalytics: {
          // provide empty string so .env works
          token: '', // NUXT_PUBLIC_SCRIPTS_CLOUDFLARE_WEB_ANALYTICS_TOKEN
        },
      },
    },
  },
})
```## Usage ### Disabling in development When you want to use the exposed API script in development, say calling `gtag` in a component, you want to load a mocked version of the script, so that it will never load. You can do this by providing a `mock` value to the registry script.nuxt.config.ts```
export default defineNuxtConfig({
  scripts: {
    registry: {
      googleTagManager: true,
    },
  },
  $development: {
    scripts: {
      registry: {
        googleTagManager: "mock",
      },
    },
  },
})
```### Loading multiple of the same script You may have a setup where you need to load the same registry script multiple times using different configuration. By default, they will be deduped and only loaded once, to load multiple instances of the same script, you can provide a unique `key` to the script.```
const { proxy: gaOne } = useScriptGoogleAnalytics({
  id: 'G-TR58L0EF8P',
})

const { proxy: gaTwo } = useScriptGoogleAnalytics({
  // without a key the first script instance will be returned
  key: 'gtag2',
  id: 'G-1234567890',
})
``` It's important to note that when modifying the key, any environment variables you're using will break. For example, with `gtag2` as the key, you'd need to provide runtime config as following:```
export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      scripts: {
        gtag2: {
          id: '', // NUXT_PUBLIC_SCRIPTS_GTAG2_ID
        },
      },
    },
  },
})
```### Using Script Options and Script Input Registry scripts doesn't stop you from making use of the core `useScript` features, you can provide extra options to opt-in to the advanced features. - `scriptOptions` - Additional options to pass to the script. Same as [**~~useScript Options~~**](https://scripts.nuxt.com/docs/api/use-script#scriptoptions). - `scriptInput` - Additional input to pass to the script. Same as [**~~useScript Input~~**](https://scripts.nuxt.com/docs/api/use-script#scriptinput).```
import { useTimeout } from '@vueuse/core'
import { useScriptCloudflareWebAnalytics } from '#imports'

const { ready } = useTimeout(5000)
useScriptCloudflareWebAnalytics({
  token: '123',
  // HTML attributes to pass to the script element
  scriptInput: {
    'data-cf-test': 'true'
  },
  // useScript options used for advanced features
  scriptOptions: {
    trigger: ready,
    bundle: true,
  },
})
```### Loading best practices When using a registry script in multiple pages or components, it's recommended to either initialize the script in your `app.vue` or your `nuxt.config` with the required options. Any subsequent calls to the registry script will use the same instance of the script, not requiring any options.```
export default defineNuxtConfig({
  scripts: {
    registry: {
      // loads the script
      fathomAnalytics: {
        site: 'SITE_ID',
      }
    }
  }
})
``````
<script setup lang="ts">
const { proxy } = useScriptFathomAnalytics() // no options required
</script>

<template>
  <button @click="proxy.trackGoal('GOAL_ID')">
    Track Goal
  </button>
</template>
``` Alternatively you can wrap the registry script in a composable to allow for easier instantiation of the script.```
export function useFathomAnalytics() {
  return useScriptFathomAnalytics({
    site: 'SITE_ID',
  })
}
```## Extending the Script Registry You can extend the script registry using the `scripts:registry` hook in your `nuxt.config.ts`:nuxt.config.ts```
import { createResolver } from '@nuxt/kit'

const { resolve } = createResolver(import.meta.url)

export default defineNuxtConfig({
  modules: ['@nuxt/scripts'],

  hooks: {
    'scripts:registry': function (registry) {
      registry.push({
        category: 'custom',
        label: 'My Custom Analytics',
        logo: '<svg>...</svg>', // optional
        import: {
          name: 'useScriptMyAnalytics',
          from: resolve('./composables/useScriptMyAnalytics'),
        },
      })
    },
  },

  devtools: {
    enabled: true,
  },
})
``` Then create your custom script composable:composables/useScriptMyAnalytics.ts```
import { useRegistryScript } from '#nuxt-scripts/utils'
import { object, string } from '#nuxt-scripts-validator'

export interface MyAnalyticsApi {
  track: (event: string, data?: Record<string, any>) => void
  identify: (userId: string) => void
}

// Schema for validation and DevTools metadata
const MyAnalyticsSchema = object({
  apiKey: string(),
})

export function useScriptMyAnalytics<T extends MyAnalyticsApi>(options?: {
  apiKey: string
  scriptOptions?: NuxtUseScriptOptions
}) {
  return useRegistryScript<T, typeof MyAnalyticsSchema>('myAnalytics', () => ({
    scriptInput: {
      src: 'https://analytics.example.com/sdk.js',
    },
    scriptOptions: {
      ...options?.scriptOptions,
      use() {
        // Initialize your script
        window.MyAnalytics.init(options?.apiKey)
        return window.MyAnalytics as T
      },
    },
  }), options, { schema: MyAnalyticsSchema })
}
```### Using Custom Registry Scripts Once registered, your custom scripts work exactly like built-in registry scripts:pages/index.vue```
<script setup>
// Auto-imported from your registry
const { proxy, status } = useScriptMyAnalytics({
  apiKey: 'your-api-key',
  scriptOptions: {
    trigger: 'onNuxtReady'
  }
})

// Use the script API
function trackClick() {
  proxy.track('button_click', { button: 'hero-cta' })
}
</script>

<template>
  <button @click="trackClick">
    Track This Click
  </button>
  <div>Status: {{ status }}</div>
</template>
```### DevTools Integration When you include a validation schema, Nuxt Scripts automatically populates DevTools metadata with your script's configuration. The `registryKey` and `registryMeta` are automatically set in development mode, allowing you to: [~~Edit this page~~](https://github.com/nuxt/scripts/edit/0.x/docs/content/docs/v0/1.guides/1.registry-scripts.md) [~~Markdown For LLMs~~](https://scripts.nuxt.com/docs/v0/guides/registry-scripts.md) [**Key Concepts** Learn about the key concepts of Nuxt Scripts.](https://scripts.nuxt.com/docs/v0/guides/key-concepts) [**Script Triggers** Control when scripts load with Nuxt Scripts' flexible trigger system.](https://scripts.nuxt.com/docs/v0/guides/script-triggers)**On this page **- [Features](#features) - [Usage](#usage) - [Extending the Script Registry](#extending-the-script-registry)