I'm trying to add a clucth.co widget to a Gatsby site, but it does not render. I've tried using react Helmet for the <script>
part, but it still does not work.
Hopefully I'm missing something simple here, but looking at other solutions I can't find anything that works.
For reference:
<script type="text/javascript" src=".js"></script>
<div className="clutch-widget" data-url="; data-widget-type="7" data-height="65" data-clutchpany-id="XXXXXXX"></div>
I'm trying to add a clucth.co widget to a Gatsby site, but it does not render. I've tried using react Helmet for the <script>
part, but it still does not work.
Hopefully I'm missing something simple here, but looking at other solutions I can't find anything that works.
For reference: https://clutch.co/content/add-review-widget-your-website
<script type="text/javascript" src="https://widget.clutch.co/static/js/widget.js"></script>
<div className="clutch-widget" data-url="https://widget.clutch.co" data-widget-type="7" data-height="65" data-clutchpany-id="XXXXXXX"></div>
Share
Improve this question
edited Aug 20, 2022 at 6:51
Ferran Buireu
29.4k7 gold badges46 silver badges72 bronze badges
asked Aug 19, 2021 at 11:18
CalHCalH
754 bronze badges
1
- good day - can you please help me: what is a clutch widget!? – zero Commented Jun 22, 2023 at 17:37
2 Answers
Reset to default 4You have multiple ways of inserting a third-party script in Gatsby. The problem you'll face in all of them is that you need to await that your div
:
<div className="clutch-widget" data-url="https://widget.clutch.co" data-widget-type="7" data-height="65" data-clutchpany-id="XXXXXXX"></div>
Needs to be rendered your script won't be able to load.
Using Script
ponent (2022 update)
Since the release of the Script
Gatsby ponent (powered by Partytown) it's much easier adding third-party scripts. Just:
import React from "react"
import { Script } from "gatsby"
function YourPage() {
return <Script src="https://my-example-script" />
}
export default YourPage
Using Helmet
:
You said you already tried but it should. You may need to try the drop-in support that adds the gatsby-plugin-react-helmet
. Then:
<Layout>
<SEO title="Live" />
<Helmet>
<script src="https://tlk.io/embed.js" type="text/javascript"/>
</Helmet>
</Layout>
Check the patibility issues when used with hooks.
Using onRenderBody
API from gatsby-ssr.js
:
Gatsby exposes a setHeadComponents
function in the onRenderBody
API that you can take advantage from:
import React from "react"
export const onRenderBody = ({ setHeadComponents }, pluginOptions) => {
setHeadComponents([
<script key="tracking"
src="https://widget.clutch.co/static/js/widget.js
type="text/javascript"
async
/>,
])
}
This snippet above will insert the <script>
in the <head>
tag of the piled HTML.
Here you have another approach using dangerouslySetInnerHTML:
setHeadComponents([
<script dangerouslySetInnerHTML={{whateveryouneedtoset}}>
])
Extracted from Unable to Inject 3rd Party Scripts in Gatsby
Modifying directly the html.js
:
You can customize even more the output of the resultant HTML by modifying the html.js
, the boilerplate that uses Gatsby to build your entire site.
Run:
cp .cache/default-html.js src/html.js
Or alternatively, copy the default-html.js
from .cache
folder into /src
and rename it to html.js
. When piling, if the html.js
is present, Gatsby will take it to build your site based on that skeleton.
You'll have something like:
import React from "react"
import PropTypes from "prop-types"
export default function HTML(props) {
return (
<html {...props.htmlAttributes}>
<head>
<meta charSet="utf-8" />
<meta httpEquiv="x-ua-patible" content="ie=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
{props.headComponents}
</head>
<body {...props.bodyAttributes}>
{props.preBodyComponents}
<div
key={`body`}
id="___gatsby"
dangerouslySetInnerHTML={{ __html: props.body }}
/>
{props.postBodyComponents}
</body>
</html>
)
}
HTML.propTypes = {
htmlAttributes: PropTypes.object,
headComponents: PropTypes.array,
bodyAttributes: PropTypes.object,
preBodyComponents: PropTypes.array,
body: PropTypes.string,
postBodyComponents: PropTypes.array,
}
There you can add your <script>
directly:
<head>
<meta charSet="utf-8" />
<meta httpEquiv="x-ua-patible" content="ie=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<script type="text/javascript" src="https://widget.clutch.co/static/js/widget.js"></script>
{props.headComponents}
</head>
Using gatsby-plugin-load-script
:
Just install and use the plugin:
{
resolve: 'gatsby-plugin-load-script',
options: {
src: 'https://widget.clutch.co/static/js/widget.js',
},
},
Hacking the gatsby-browser.js
API:
If none of the above fits you, you can still use one of gatsby-browser.js
APIs (onClientEntry
) to manually add script given a source URL:
const addScript = url => {
const script = document.createElement("script")
script.src = url
script.async = true
document.body.appendChild(script)
}
export const onClientEntry = () => {
window.onload = () => {
addScript("https://widget.clutch.co/static/js/widget.js")
}
}
In order to not have the clutch widget disappear on route changes, I ended up running the Init
and Destroy
methods from window.CLUTCHCO
myself in useEffect
.
React.useEffect(() => {
// add widget to end of body and run it
const script = document.createElement("script")
script.type = "text/javascript"
script.src = "https://widget.clutch.co/static/js/widget.js"
script.async = true
document.body.appendChild(script)
// run script
script.onload = () => {
// @ts-expect-error Apparently we have to manually do this!!