wannabeprogrammer
wannabeprogrammer

Reputation: 131

How to embed a <script> widget in next.js only on a certain page?

I am trying to load an external script which embedds the "Buy Me A Coffee" widget onto a site. I am unable to get the script to execute unless I place the script in the _app.js file. But by adding the script to the _app.js file the widget is loaded on every page. I only want it loaded on a single page so I tried added the script to the head of the page I would like it loaded on:

<Head>
// Some content
  <Script data-name="BMC-Widget" data-cfasync="false" src="https://cdnjs.buymeacoffee.com/1.0.0/widget.prod.min.js" data-id="some-id" data-description="Support me on Buy me a coffee!" data-message="" data-color="#5F7FFF" data-position="Right" data-x_margin="18" data-y_margin="18"/>
</Head>

that did not work and the docs say to add Script tags outside of the Head tags so I moved the script outside of the head tag like so:

<Head>
// Some content
</Head>
<Script data-name="BMC-Widget" data-cfasync="false" src="https://cdnjs.buymeacoffee.com/1.0.0/widget.prod.min.js" data-id="some-id" data-description="Support me on Buy me a coffee!" data-message="" data-color="#5F7FFF" data-position="Right" data-x_margin="18" data-y_margin="18"/>

But that still did not work. The widget is just not loading on the site unless I put the script into the _app.js file.

I've read the documentation on the Script and Head tags for next.js but that is not helping out with this. I could definitely use some help with getting this to work.

Upvotes: 3

Views: 2402

Answers (3)

Laxman
Laxman

Reputation: 11

Here is a simple Buy Me A Coffee Widget as a component. Edit the username, color and position.

'use client';

import { useEffect } from 'react';

export function BuyMeACoffee() {
  useEffect(() => {
    const script = document.createElement('script');
    script.setAttribute('data-name', 'BMC-Widget');
    script.src = 'https://cdnjs.buymeacoffee.com/1.0.0/widget.prod.min.js';
    script.setAttribute('data-id', 'thaletto');
    script.setAttribute('data-description', 'Support me on Buy me a coffee!');
    script.setAttribute('data-message', '');
    script.setAttribute('data-color', '#8FDCC2');
    script.setAttribute('data-position', 'Right');
    script.setAttribute('data-x_margin', '18');
    script.setAttribute('data-y_margin', '18');
    script.async = true;

    script.onload = function () {
      const event = new CustomEvent('DOMContentLoaded', {
      bubbles: true,
      cancelable: true,
    });
    window.dispatchEvent(event);
  };

  document.head.appendChild(script);

  return () => {
    document.head.removeChild(script);
    const widget = document.getElementById('bmc-wbtn');
    if (widget) {
      document.body.removeChild(widget);
    }
  };
  }, []);

  return null;
}

Upvotes: 1

Mose Schrute
Mose Schrute

Reputation: 1

The buymeacoffee script loads the widget when the window is DOMContentLoaded event is fired (as seen in this answer). So you can use @dpacman's answer along with a content strategy of 'beforeInteractive'

Upvotes: 0

dpacman
dpacman

Reputation: 3899

I had the same problem, this is how you add a third-party script in next.js.

<Head>
// Some content
</Head>
<Script
    strategy="afterInteractive"
    dangerouslySetInnerHTML={{
      __html: `
      (function (d, s, id) {
              var js,
                el = d.getElementsByTagName(s)[0];
              if (d.getElementById(id)) {
                return;
              }
              js = d.createElement(s);
              js.async = true;
              js.src = "https://cdnjs.buymeacoffee.com/1.0.0/widget.prod.min.js";
              js.id = id;
              js.charset = "UTF-8";
              el.parentNode.insertBefore(js, el);
      })(document, "script", "buymeacoffee-js");
    `,
   }}
/>

Upvotes: 2

Related Questions