I'd like to know where I should add the <script></script> provided by Google Adsense.
They say to add it into the <head></head>, but in Gatsby you have Helmet as <head>.
I tried also to add the script inside an html.js file where it's located a <head> tag with {``} to escape the <script> tag, but it outputs at the top of the website the script content.
TL;DR: What is the optimal way to add Adsense to a website built with GatsbyJS?
I've tried to use the react adsense package but I do not understand how to use it with Gatsby.
I have tried to add the <script> tag to html.js and it doesn't compile.
If you escape it with {``} you get the script as is, on top of the website.
<head>
<meta charSet="utf-8" />
<meta httpEquiv="x-ua-compatible" content="ie=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
{this.props.headComponents}
{`<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>`}
{` <script>
(adsbygoogle = window.adsbygoogle || []).push({
google_ad_client: "ca-pub-1540853335472527",
enable_page_level_ads: true
});
</script>
`}
</head>
source: html.js
The website should get detected by the Google crawlers.
Thanks to an answer given on Github, finally the problem is solved:
If you want to add Adsense:
cp .cache/default-html.js src/html.js
Add the script but everything inside should be escaped -> {<some-js-code-here>}
In my situation and as an example:
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<script>
{`
(adsbygoogle = window.adsbygoogle || []).push({
google_ad_client: "ca-pub-1540853335472527",
enable_page_level_ads: true
});
`}
</script>
if you are using services like Netlify to deploy your website, you can use snippet injection functionality to make this work without touching your source code.
settings -> build & deploy -> post processing -> snippet injection -> add snippet
then you can select where you want to add the snippet (script tag). For the Adsense this should be before the </head>. hope it helps. :)
You can find here a nice tutorial on how to add Google AdSense in Gatsby.
Basically, the suggested way is to implement a Google AdSense Banner using React and including the Google AdSense code in the gatsby-ssr.js file.
gatsby-ssr.js file:
const React = require('react')
const HeadComponents = [
<script
src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-XXXX"
crossOrigin="anonymous"
async
/>,
]
exports.onRenderBody = ({ setHeadComponents }, pluginOptions) => {
setHeadComponents(HeadComponents)
}
AdSense Banner component:
const Banner: React.FC<BannerProps> = ({
className,
style,
layout,
format,
client = 'ca-pub-XXXX',
slot,
responsive,
layoutKey,
}) => {
useEffect(() => {
try {
const adsbygoogle = window.adsbygoogle || []
adsbygoogle.push({})
} catch (e) {
console.error(e)
}
}, [])
return (
<div className={clx(container, className)}>
<ins
className="adsbygoogle"
style={style}
data-ad-layout={layout}
data-ad-format={format}
data-ad-client={client}
data-ad-slot={slot}
data-ad-layout-key={layoutKey}
data-full-width-responsive={responsive}
/>
</div>
)
}
Don't use the gatsby-adsense plugin, it's deprecated.
Full article here.
To set up Adsense, place the <script> tag (without template literals {``} just before your closing </body> tag in your html.js, like this:
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
</body>
Then, to place an ad unit, you can either use a pre-built component like react-adsense on npm, as you mentioned, or build it yourself.
This is a useful article that covers both the setup and the placing of ad units with a component.
Let me know if this works for you or if something isn't clear!
To add Google Adsence in Gatsby you need these three packages
react-adsense rehype-react gatsby-transformer-remark
and if you want to know how to implement these packages in your site then checkout this tutorial
Related
This is a 2-part question that is related (somewhat):
Part I: Rendering HTML output via getStaticProps in the "View Page Source" view.
For SEO reasons, I'd like my Next.js frontend application to return HTML output in the "View Page Source" view (in Google Chrome) instead of JSON.
I'm using getStaticProps() to return some data from my backend Django app. I built the same page and functionality in React Remix Run, and I CAN see my HTML output. However, I'd like this to render the full HTML (instead of JSON) in my Next.js app so that I don't have to rewrite the entire application in Remix.
Here's my code:
Next.js code
export const getStaticProps = async (context) => {
const { slug } = context.params
const product = await fetchProductDetails(slug)
const otherProductsList = await fetchProducts()
const error = product.error ? product.error : ''
return {
props: {
product,
otherProductsList,
error
},
revalidate: 15
}
}
// Functional component
const ProductDetails = ({ product, otherProductsList, error }) => {
// my client side code...
return (
// my JSX code that displays the product data using {product.name},
{product.price}, etc.
// The "View Page Source" view does not show this JSX element as an h1 tag.
// Instead, it shows all of the JSON being returned from the DB.
<h1>{product.name}</h1>
)
}
Example source code output shown in "View Page Source" view:
<!DOCTYPE html>
<html>
<head>
<meta charSet="utf-8"/>
<meta name="viewport" content="width=device-width"/>
<meta name="next-head-count" content="2"/>
<link rel="preload" href="/_next/static/css/75fa4eff9b884fe2.css" as="style"/>
<link rel="stylesheet" href="/_next/static/css/75fa4eff9b884fe2.css" data-n-g=""/>
<link rel="preload" href="/_next/static/css/eafeef7863427731.css" as="style"/>
<link rel="stylesheet" href="/_next/static/css/eafeef7863427731.css" data-n-p=""/>
<noscript data-n-css=""></noscript>
<script defer="" nomodule="" src="/_next/static/chunks/polyfills-5cd94c89d3acac5f.js"></script><script src="/_next/static/chunks/webpack-dd2ed5d38a88a4b3.js" defer=""></script><script src="/_next/static/chunks/framework-0f8b31729833af61.js" defer=""></script><script src="/_next/static/chunks/main-83d2e1974cccf08f.js" defer=""></script><script src="/_next/static/chunks/pages/_app-fa3d7135221d445a.js" defer=""></script><script src="/_next/static/chunks/885-9d94ce365372990b.js" defer=""></script><script src="/_next/static/chunks/341-e930103f26cccc8f.js" defer=""></script><script src="/_next/static/chunks/418-874816ac548e7a1e.js" defer="">
// LOTS OF JSON OUTPUT HERE - THIS SHOULD BE HTML INSTEAD
</script>
</html>
Any idea why Next.js is returning JSON in the "View Page Source" view instead of JSON despite using getStaticProps() to fetch the data?
NOTE: I also tried removing my useEffect() hook (which is currently used to handle "success" operations), and I'm still getting JSON output. Also to note, the HTML markup actually shows as expected in the Google Chrome Inspect window.
Part 2: Setting <meta property> tags in Next.js on the page level.
I am also trying to set <meta property> tags on the page level (every page has a different meta property) so that my thumbnails and title text can be accessed through link sharing on social media platforms. For example, if I copy a link to a product page from my Next.js application, and post it to my Twitter feed, Twitter should pull the product thumbnail, title, description, etc.
I already know what code to write to make this work, but as related to the above problem, these tags are not showing in "View Page Soruce".
Are these two problems related?
I have a GatsbyJS site that I am working on where the main content source is a Wordpress install. One of the things I like to add to my sites is the ability to have placeholder areas in the site where I can control the content via the CMS. Usually I have a header_scripts area that goes at the bottom of the <head> tag, a body_scripts area that goes at the start of the <body> tag, and a footer_scripts area that goes at the bottom of the page <body>. With these three, I can usually integrate third-party add-ins pretty easily without having to do code deployments.
Sometimes I need to embed stylesheets, sometimes I need to embed script tags, and sometimes I need to throw in <meta> tags. Really the content could be anything. This data comes back as a raw string from my Wordpress GraphQL endpoint.
So now my question is, how do I get this content injected into my Gatsby site in the following places:
<html>
<head>
...
{header_scripts}
</head>
<body>
{body_scripts}
...
{footer_scripts}
</body>
</html>
I've found so far that I can just include the body_scripts and footer_scripts in a fairly regular manner in my Gatsby page template. In gatsby-node.js, I pass in the property values using the pageContext. It's kind of a bummer that they need to be wrapped in a <div /> tag, but they seem to work just fine.
import React from 'react'
export default class PageTemplate extends React.Component {
render = () => {
return (
<React.Fragment>
{this.props.pageContext.bodyScripts && (
<div dangerouslySetInnerHTML={{__html:this.props.pageContext.bodyScripts}} />
)}
{/* my page content here */}
{this.props.pageContext.footerScripts && (
<div dangerouslySetInnerHTML={{__html:this.props.pageContext.footerScripts}} />
)}
</React.Fragment>
)
}
}
Now for the real question. I am stumped on how to get the dynamic content from the header_scripts into the Gatsby server-side-rendering <head> tag. The closest thing I have found to being able to inject content into the head is to leverage the gatsby-ssr.js onRenderBody function. However, this seems to require pre-determined React component instances in order to function. I can't just pass it in plain raw string content and see the output in the page source:
export const onRenderBody = async ({
pathname,
setHeadComponents,
setHtmlAttributes,
setBodyAttributes,
setPreBodyComponents,
setPostBodyComponents,
setBodyProps
}, pluginOptions) => {
setHeadComponents(['<script>alert("hello");</script>'])
}
This results in an escaped string getting inserted into the <head> tag:
<html>
<head>
...
<script>alert("hello");</script>
</head>
<body>
...
</body>
</html>
I'm at a loss as to how to proceed. I can't just wrap my string in a <div /> tag like in the body because div tags can't go inside the head tag. I can't think of any head-capable HTML tags that would accept this kind of content.
The only idea I've had is to actually parse the string content into full React components. This seems daunting given the number of possible tags & formatting that I would need to support.
Am I going about this the wrong way? How can I get my arbitrary content into my Gatsby site's head tag?
It's a broad question and it will need some trials and errors to ensure that it's fully working without caveats in all scenarios but, among the things you've tried, you can add a few more options to the list to check which ones fit better.
Regarding the body_scripts and footer_scripts both can be inserted using the:
<div dangerouslySetInnerHTML={{__html:this.props.pageContext.footerScripts}} />
In any desired page or template. For the header_scripts and the meta tags (SEO), you can use the <Helmet> component. Basically, using this component, everything that is wrapped inside, it's becomes transpiled inside the <head> tag once compiled.
export default class PageTemplate extends React.Component {
render = () => {
return (
<React.Fragment>
<Helmet>
{this.props.pageContext.headerScripts && (
<div dangerouslySetInnerHTML={{__html:this.props.pageContext.headScripts}} />
)}
</Helmet>
{this.props.pageContext.bodyScripts && (
<div dangerouslySetInnerHTML={{__html:this.props.pageContext.bodyScripts}} />
)}
{/* my page content here */}
{this.props.pageContext.footerScripts && (
<div dangerouslySetInnerHTML={{__html:this.props.pageContext.footerScripts}} />
)}
</React.Fragment>
)
}
}
However, if the data comes from a CMS, it won't be available in the SSR yet, so, one easy thing you can do is to customize the outputted HTML (html.js) that Gatsby generates in each compilation. From the docs:
Customizing html.js is a workaround solution for when the use of the
appropriate APIs is not available in gatsby-ssr.js. Consider using
onRenderBody or onPreRenderHTML instead of the method above. As a
further consideration, customizing html.js is not supported within a
Gatsby Theme. Use the API methods mentioned instead.
Run:
cp .cache/default-html.js src/html.js
Or manually, copy the .cache/default-html.js file and paste it /src folder. There you can customize the final HTML.
I am trying to embed a public FB post into the main page of my application. I am following FB guide and it's pretty simple. It works when I do it in .html file, but doesn't with Next JS.
Basically, instructions are that you need to insert this right after the body opening tag
<div id="fb-root"></div>
<script async defer crossorigin="anonymous"
src="https://connect.facebook.net/en_US/sdk.js#xfbml=1&autoLogAppEvents=1&version=v9.0&appId={appId}" nonce={someNonce}"></script>
and then you put the other part wherever you want.
I even created a custom _document.js file and included this script, I can also see it in the browser. But the post does not get loaded.
Anyone had this kind of issue?
Assuming you already have the JS SDK loaded in your document, like you mentioned (you might also load the script on-demand via JavaScript if preferred).
// pages/_document
class MyDocument extends Document {
render() {
return (
<Html lang="en">
<!-- additional code -->
<body>
<!-- additional code -->
<script
async
defer
src="https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v3.2"
/>
</body>
</Html>
);
}
}
You can then render a Facebook post inside one of your components with:
<div
className="fb-post"
data-href="https://www.facebook.com/20531316728/posts/10154009990506729/"
/>
For further details refer to the official Embedded Posts documentation.
I try to create a React app inside visualforce page via lightning. When I click preview in visualforce setting, everything is fine.
But when I use it in Lightning app builder it does not work. It shows
The error: Refused to frame 'https://mirage-video-dev-ed--ltng.container.lightning.com/' because an ancestor violates the following Content Security Policy directive: "frame-ancestors https://mirage-video-dev-ed--c.visualforce.com".
Also really weird that if I right click and choose "Reload frame", it works.
Visualforce code
<apex:page >
<apex:includeLightning />
<div id="hello" />
<script>
$Lightning.use("c:myFirstApp", function() {
$Lightning.createComponent("lightning:container",
{ src: "{!$Resource.hello + '/index.html'}"},
"hello",
function(cmp) {
console.log("created");
// do some stuff
}
);
});
</script>
</apex:page>
myFirstApp
<aura:application access="global" extends="ltng:outApp">
<aura:dependency resource="lightning:container"/>
</aura:application>
Is there a way to fix it? I cannot find the way to load aura:application directly so if there is a way please show me.
You've got a bit of a inception problem going on... You just need to mount your react app directly inside of the VF page. No need to use a lightning:container.
See my B.A.S.S. project. This is proven to work and be extremely scalable.
Example VF Page with react app:
<apex:page showHeader="true" sidebar="false" standardStylesheets="false" docType="html-5.0">
<script type="text/javascript">
//rest details
const __ACCESSTOKEN__ = '{!$Api.Session_ID}';
const __RESTHOST__ = '';
</script>
<div id="root"></div>
<!-- Your react entry point -->
<script type='text/javascript' src="{!URLFOR($Resource.app, 'dist/app.js')}"></script>
</apex:page>
It is also possible to to run a React App directly inside a LWC, although no recommended.
I am using the Chrome toolbar from http://wave.webaim.org/extension/ to check the ADA compliance of my React-Bootstrap app.
When I use a Popover within an OverlayTrigger without an ID, it warns me in the console:
Warning: Failed propType: The prop 'id' is required to make 'Popover' accessible for users using assistive technologies such as screen readers
Problem is, when I add an ID to the Popover, I then get the following error on my accessibility scan:
Broken ARIA reference: An element has an aria-labelledby or aria-describedby value that does not match the id attribute value of another element in the page.
I am guessing it's happening because the element with that ID doesn't exist until the button is clicked. Am I missing something, or is this element not ADA compliant? Or, is this just a problem with the scan, and there's a better tool I should be using to prove my site is compliant?
Here is the code for an example site that demonstrates the issue. I have thrown it in a Fiddle, but it won't do you much good because if you run the accessibility tool on that, it will give you JSFiddle's errors rather than the ones for the relevant code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>React-Bootstrap Popover Accessibility</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.5/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.5/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-bootstrap/0.28.1/react-bootstrap.js"></script>
<link type="text/css" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"/>
</head>
<body>
<div id="container"></div>
<script type="text/babel">
var Button = ReactBootstrap.Button;
var OverlayTrigger = ReactBootstrap.OverlayTrigger;
var Popover = ReactBootstrap.Popover;
var Overlay = React.createClass({
render: function() {
return (
<OverlayTrigger trigger="click" placement="right" overlay={
<Popover title="Popover" id="popover-id">Here's the contents of the popover</Popover>
}>
<Button bsStyle="primary">Click to see Popover</Button>
</OverlayTrigger>
);
}
});
ReactDOM.render(
<Overlay />,
document.getElementById('container')
);
</script>
</body>
</html>
I can confirm that the code is not compliant. You can double-check whether this code validates by:
Inspecting this element in the developer console (before the button is clicked)
Copying the rendered HTML to the clipboard
Loading http://validator.nu and selecting the ‘Textfield’ option
Pasting your HTML between the <body></body>tags
Clicking ‘Validate’
As you’ll see, the code does not validate, because, as oobgam mentioned, the target ID is not initially present in the DOM.
There are a number of different approaches to fixing this. Once I understand which design pattern you’re trying to accessibly support, I can provide more concrete advice.
Can you please provide more information about why you chose this implementation? How do you see desktop and mobile users interacting with this, and to what end?
Quora has a good list of related patterns at What's the difference between a modal, a popover and a popup?