Source:  Twitter logo

I am trying to add an external embed code to my Gatsby page.

I currently use

import React from 'react'
import Link from 'gatsby-link'


let test ="<script type='text/javascript'>
(function(d, s) {
    var useSSL = 'https:' == document.location.protocol;
    var js, where = d.getElementsByTagName(s)[0],
    js = d.createElement(s);
    js.src = (useSSL ? 'https:' : 'http:') +  '//www.peopleperhour.com/hire/1002307300/1213788.js?width=300&height=135&orientation=vertical&theme=light&rnd='+parseInt(Math.random()*10000, 10);
    try { where.parentNode.insertBefore(js, where); } catch (e) { if (typeof console !== 'undefined' && console.log && e.stack) { console.log(e.stack); } }
}(document, 'script'));
</script>"

const ContactPage = () => (

    <div>
        <h1>ContactPage</h1>
        <div
            dangerouslySetInnerHTML={{ __html: test }}
          />
    </div>

)

export default ContactPage

which is full of syntax errors. Can you please point out a better way to include raw snippets in a react component?

Is there alternatively a place in Gatsby to add all additional scripts like custom scripts, Google Analytics, icon fonts, animate.js and anything else I may need?

Thank you for the help

You can inject external scripts (with no npm modules) to gatsby.js project in many ways. Prefer to use respective gatsby-plugin for "web-analytics" scripts.

Using require() :

  • Create a file in your project myScript.js and paste the script content
  • Add const myExtScript = require('../pathToMyScript/myScript')
    to a statefull component at the Pages folder inside render() and before return() if you want to execute that script only at that page(=page/component scope).

    export default class Contact extends React.Component {  
      render() {  
       const myExtScript = require('../pathToMyScript/myScript')  
        return (
          ........       
                   )}
    
  • If you want to execute script in the global scope (=in every page/ component):
    add it in html.js

    <script dangerouslySetInnerHTML= {{ __html: ` 
        putYourSciptHereInBackticks `}} />`  
    

    before closing the </body>. It is better to manipulate/monitor your global scope at this component because it has this specific purpose... to inject html to every page/route globally.

  • Another way to inject at the global scope is with require() before the component declaration. This will work but it's not a good practice, as your components shouldn't inject anything globally.

     const myExtScript = require('../pathToMyScript/myScript')  
    
       export default class Contact extends React.Component {  
        render() {  
          return (
          ........       
                   )}
    

P.S. Sorry if the answer is not edited properly. This my first answer at StackOverflow.

26 users liked answer #0dislike answer #026
AndreasT profile pic
AndreasT

Use React-Helmet

First import Helmet from 'react-helmet'

Inside your div you can do like this

<Helmet>
<script type='text/javascript'>
(function(d, s) {
    var useSSL = 'https:' == document.location.protocol;
    var js, where = d.getElementsByTagName(s)[0],
    js = d.createElement(s);
    js.src = (useSSL ? 'https:' : 'http:') +  '//www.peopleperhour.com/hire/1002307300/1213788.js?width=300&height=135&orientation=vertical&theme=light&rnd='+parseInt(Math.random()*10000, 10);
    try { where.parentNode.insertBefore(js, where); } catch (e) { if (typeof console !== 'undefined' && console.log && e.stack) { console.log(e.stack); } }
}(document, 'script'));
</script>
</Helmet>
11 users liked answer #1dislike answer #111
Mohit Bajoria profile pic
Mohit Bajoria

Apparently using a multiline JS syntax did the trick, as in

let test = "<script type='text/javascript'>\
(function(d, s) {\
    var useSSL = 'https:' == document.location.protocol;\
    var js, where = d.getElementsByTagName(s)[0],\
    js = d.createElement(s);\
    js.src = (useSSL ? 'https:' : 'http:') +  '//www.peopleperhour.com/hire/1002307300/1213788.js?width=300&height=135&orientation=vertical&theme=light&rnd='+parseInt(Math.random()*10000, 10);\
    try { where.parentNode.insertBefore(js, where); } catch (e) { if (typeof console !== 'undefined' && console.log && e.stack) { console.log(e.stack); } }\
}(document, 'script'));\
</script><div id='pph-hireme'></div>"

alternatively, you can do

let test2 = `
<script type='text/javascript'>
(function(d, s) {
    var useSSL = 'https:' == document.location.protocol;
    var js, where = d.getElementsByTagName(s)[0],
    js = d.createElement(s);
    js.src = (useSSL ? 'https:' : 'http:') +  '//www.peopleperhour.com/hire/1002307300/1213788.js?width=300&height=135&orientation=vertical&theme=light&rnd='+parseInt(Math.random()*10000, 10);\
    try { where.parentNode.insertBefore(js, where); } catch (e) { if (typeof console !== 'undefined' && console.log && e.stack) { console.log(e.stack); } }\
}(document, 'script'));
</script><div id='pph-hireme'></div>
`

Any more comments are welcome

2 users liked answer #2dislike answer #22
Giannis Dallas profile pic
Giannis Dallas

One way - perhaps the preferred way - is using the SSR file.

From the docs:

The file gatsby-ssr.js lets you alter the content of static HTML files as they are being Server-Side Rendered (SSR) by Gatsby and Node.js. To use the Gatsby SSR APIs, create a file called gatsby-ssr.js in the root of your site. Export any of the APIs you wish to use in this file.

A tutorial on how to do that is here.

It uses the setHeadComponents method to inject into html.js:

setHeadComponents

It takes an array of components as its first argument which will be added to head components during building time and which will be passed to html.js.

2 users liked answer #3dislike answer #32
rmcsharry profile pic
rmcsharry

There is another way, which is creating a React's effects:

import { useEffect } from 'react'

const useGoogleAnalytics = () => {

    useEffect(() => {
        // GA Snippet
    }, [])

    return null
}

And then you can use useGoogleAnalytics() in the page components you want to include.

The main advantage of this are:

  • You get transpilation of the code
  • It's way easier to maintain for more complex code than inside a template literal.

For simple scripts like Google Analytics I'd go for a template literal, but for custom and subject-to-change snippet I'd prefer an effect. As long as you don't abuse of those, It should not impact performance nor create overhead.

Does anyone see other disadvantages with this other method?

0 users liked answer #4dislike answer #40
jonalvarezz profile pic
jonalvarezz

Copyright © 2022 QueryThreads

All content on Query Threads is licensed under the Creative Commons Attribution-ShareAlike 3.0 license (CC BY-SA 3.0).