---
title: useScript()
description: A powerful API for loading third-party scripts with optimized performance
new: true
---

The `useScript` composable provides an enhanced developer experience for loading third-party scripts with intelligent defaults for performance, security, and lifecycle management.

## Basic Usage

```ts
import { useScript } from '@unhead/dynamic-import'

const { onLoaded } = useScript('https://example.com/script.js')

onLoaded(() => {
  // Script loaded successfully
  console.log('Script is ready to use')
})
```

## Smart Defaults

A singleton pattern is implemented so scripts with the same `src` or `key` are only loaded once globally. This helps prevent duplicate script loading and ensures consistent initialization.

The following defaults are applied for optimal performance and security:

- Scripts load after hydration by default
- `defer`{lang="html"} enabled for proper execution order
- `fetchpriority="low"`{lang="html"} to prioritize critical resources
- `crossorigin="anonymous"`{lang="html"} prevents cookie access
- `referrerpolicy="no-referrer"`{lang="html"} blocks referrer headers

## Input Options

### Simple URL

Pass a URL string for the quickest implementation:

```ts
import { useScript } from '@unhead/dynamic-import'

useScript('https://example.com/script.js')
```

### Full Configuration

Pass an options object to customize any `<script>`{lang="html"} attribute:

```ts
import { useScript } from '@unhead/dynamic-import'

useScript({
  src: 'https://example.com/script.js',
  id: 'my-script',
  async: true,
  defer: false,
  crossorigin: false, // disable crossorigin='anonymous'
  // Any valid script attribute can be used
})
```

## Loading Control

Fine-tune when and how scripts load with the second parameter:

```ts
import { useScript } from '@unhead/dynamic-import'

useScript('https://example.com/script.js', {
  // When to load the script
  trigger: 'client', // | 'server' | Promise | ((load) => void)

  // Resource hint strategy
  warmupStrategy: 'preload', // | 'prefetch' | 'preconnect' | 'dns-prefetch',

  // Access the script's API
  use: () => window.externalAPI
})
```

### Loading Triggers

Control precisely when scripts load with different trigger strategies:

```ts
import { useScript } from '@unhead/dynamic-import'

// Load immediately on the client (default)
useScript(src, { trigger: 'client' })

// Load during server rendering
useScript(src, { trigger: 'server' })

// Load when a promise resolves
useScript(src, {
  trigger: new Promise(resolve =>
    setTimeout(resolve, 3000)
  )
})

// Custom load function
useScript(src, {
  trigger: (load) => {
    document.getElementById('load-button').addEventListener('click', load)
  }
})
```

## Script Lifecycle

The script passes through these lifecycle states:

- `awaitingLoad` - Initial state
- `loading` - Script is loading
- `loaded` - Script loaded successfully
- `error` - Script failed to load
- `removed` - Script was removed

Monitor these states with lifecycle hooks:

```ts
import { useScript } from '@unhead/dynamic-import'

const script = useScript('https://example.com/script.js')

script.onLoaded((api) => {
  // Script loaded successfully
  console.log('Script is ready')
})

script.onError(() => {
  // Script failed to load
  console.error('Script loading failed')
})
```

## Resource Hints

The `warmupStrategy` option automatically adds resource hints to optimize loading:

```ts
import { useScript } from '@unhead/dynamic-import'

useScript('https://example.com/script.js', {
  // Preload - highest priority, load ASAP
  warmupStrategy: 'preload',

  // Prefetch - load when browser is idle
  warmupStrategy: 'prefetch',

  // Preconnect - setup connection early
  warmupStrategy: 'preconnect',

  // DNS Prefetch - resolve DNS early
  warmupStrategy: 'dns-prefetch'
})
```

::tip
Choose the right strategy based on how critical the script is:
- Use `preload` for essential scripts needed soon after page load
- Use `prefetch` for scripts needed later in the user journey
- Use `preconnect` or `dns-prefetch` to optimize third-party domains
::

## API Proxying

If you need to access the script's API before it loads, use the `use` option with proxy support:

```ts
import { useScript } from '@unhead/dynamic-import'

const script = useScript({
  src: 'https://maps.googleapis.com/maps/api/js'
}, {
  use: () => window.google.maps
})

// Works before script loads!
const map = script.proxy.Map()
```

The proxy records all calls and replays them once the script is loaded, allowing you to use the API immediately in your code without worrying about loading state.

## Common Use Cases

### Google Analytics

```ts
import { useScript } from '@unhead/dynamic-import'

useScript({
  src: 'https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX',
  async: true
}, {
  trigger: 'client'
})

// Initialize gtag
useHead({
  script: [
    {
      children: `
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());
        gtag('config', 'G-XXXXXXXXXX');
      `,
      key: 'gtag-config'
    }
  ]
})
```

### Loading on User Interaction

```ts
import { useScript } from '@unhead/dynamic-import'

// Load YouTube player only when user clicks play
useScript('https://www.youtube.com/iframe_api', {
  trigger: (load) => {
    document.getElementById('play-video').addEventListener('click', () => {
      load()
      // Show loading indicator while script is loading
    })
  }
})
```

## API Reference

### Input

- `src`: String URL or object with script attributes

### Options

- `trigger`: When to load the script ('client', 'server', Promise, or custom function)
- `warmupStrategy`: Resource hint strategy ('preload', 'prefetch', 'preconnect', 'dns-prefetch')
- `use`: Function to access the script's API

### Return Value

Returns a script controller object with these properties:
- `status`: Current lifecycle state
- `onLoaded`: Register callback for successful load
- `onError`: Register callback for loading failure
- `proxy`: Proxy to the script's API (if `use` option provided)