# How to Embed a Script in NextJS

I've been using NextJS since early this summer... And I'm loving it. 😻

Today I got to use another of its cool perks, and I wanted to share it with you because it might be just the right solution for your client-side JavaScript embedding needs.

I'm talking about Next's **Script Component**

## The Problem

You want to embed an `iframe` that requires the integration of some 3rd party custom `script`. Or maybe you want to add a tracking scripts, like a Facebook Pixel or Google Analytics. Either way, you are trying to run a JS script on your page.

Traditionally, a web developer would use the HTML `<script>` tag inside the header tags.

But what if you are editing a React component somewhere down the NextJS hierarchy tree? What if you want to embed that script (or the element that needs that script) in a page that uses some custom layout component? 

Or what if your deployment host breaks your script by not loading it correctly? *─Yes I'm looking at you AWS Amplify!*

## The NextJS Solution

The Next.js `Script` component, `next/script`, is an extension of the HTML `<script>` element. It enables us to load third-party scripts anywhere in our application without needing to append the script directly to the header (which in NextJS is `Head` from `next/head`). 

On top of that, `Script` can save you time and improve loading performance because it allows us to specify when to render the script.

## Implementation

To add a third-party script to your application, simply import the `next/script` component:

```javascript
import Script from 'next/script'
```

You then pick where in you want to place your script call:

```javascript
export default function YourPage() {
  return (
    <>
      <Script src="https://your-script-link.js" />
    </>
  )
}
```

If your script generates something that needs attaching to an HTML element, you can of course simply call `Script` to load it, then add the right linkage (for example an ID):

```javascript
export default function YourPage() {
  return (
    <>
      <Script src="https://domain.com/iframe-embed/third-party-script-to-load.js" />
      <div id="your-script-element-id">
      </div>
    </>
  )
}
```



## Extra Perks

### Loading Strategy

Besides being extremely easy to place and use, with `next/script`, you can decide when to load your third-party script by using the `strategy` property:

```javascript
<Script src="https://www.google-analytics.com/analytics.js" strategy="lazyOnload" />
```

You can pick one of three strategies:

* `beforeInteractive`: Load before the page is interactive
* `afterInteractive`: (**default**): Load immediately after the page becomes interactive
* `lazyOnload`: Load during idle time

You can find out more about the difference between these on the [official documentation](https://nextjs.org/docs/basic-features/script#strategy)

### Inline Scripts

`next/script` also supports inline scripts: i.e. scripts not loaded from an external file but written within the `<Script>` tag. 

You can either place a script inside of curly braces and wrap it inside an open and close `<Sctipt>` tag:

```javascript
<Script id="show-banner" strategy="lazyOnload">
  {`document.getElementById('banner').classList.remove('hidden')`}
</Script>
```

Or you can use the [`dangerouslySetInnerHTML` property](https://lo-victoria.com/dangerouslysetinnerhtml-in-react) in a self-closing tag:

```javascript
<Script
  id="show-banner"
  dangerouslySetInnerHTML={{
    __html: `document.getElementById('banner').classList.remove('hidden')`,
  }}
/>
```
Note that: 
- You can't use the `beforeInteractive` strategy with inline scripts.
- You must provide an `id` to allow Next.js to track and optimise the script

### Executing Code After Loading 

Another cool thing you can do with `next/script` is to run some JavaScript code only *after* the script has loaded.

For example, let's say you need to run an API script and then trigger a function that displays a pop-up. You can do it that too:

```javascript
import { useState } from 'react'
import Script from 'next/script'

export default function Checkout() {
  const [stripe, setStripe] = useState(null)

  return (
    <>
      <Script
        id="stripe-js"
        src="https://js.stripe.com/v3/"
        onLoad={() => {
          setStripe({ stripe: window.Stripe('pk_test_12345') })
        }}
      />
    </>
  )
}
```

Note that you can only execute code if you are using either the `afterInteractive`  (default) or the `beforeInteractive` strategies.

### Additional Attributes

You can also add other attributes to the `Script` element that are not used directly by the component, but that you might need to pass to the final, optimised `<script>` element that is eventually outputted to the page. For example a [`nonce`](https://stackoverflow.com/questions/42922784/what-s-the-purpose-of-the-html-nonce-attribute-for-script-and-style-elements) or a [custom `data-`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/data-*) attribute.
