I have built a web app with remix run and I want to add the Google analytics. How can I add the pure JS to head and body section without making the typescript angry?
This repository helped me out a lot: https://github.com/remix-run/examples/blob/main/google-analytics
The one thing that tripped my up for a while was that I was developing on Brave browser which blocks analytics.
Switching to Chrome, Firefox, Safari should do the trick.
On any page, at anytime, you can flip between plain HTML and full
client-side transitions.
If you need one tiny bit of interactivity, use a
<script
dangerouslySetInnerHTML>.
Example, taken from https://remix.run/docs/en/v1/guides/disabling-javascript
return (
<>
<select id="qty">
<option>1</option>
<option>2</option>
<option value="contact">
Contact Sales for more
</option>
</select>
<script
dangerouslySetInnerHTML={{
__html: `
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('qty').onchange = (event) => {
if (event.target.value === "contact") {
window.location.assign("/contact")
}
}
});
`
}}
/>
</>
);
Remix is after all a React framework you have to make use of dangerouslySetInnerHTML to add the content of your setup script to your root.txt file.
I made this short "how to ? " page that you can follow https://tipminers.com/tips/50/How-to-add-google-analytics-to-a-Remix-Run-Web-App
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 found alot of outdated options on the web so Just wandering what should be the best approach to convert DOM, as an PDF attachment and then send it via email.
I am using React as Front-end and .Net Core web Api as backend.
Thanks in Advance :)
Download jsPDF from Github Include these scripts below:
jspdf.js
jspdf.plugin.from_html.js
jspdf.plugin.split_text_to_size.js
jspdf.plugin.standard_fonts_metrics.js
If you want to ignore certain elements, you have to mark them with an
ID, which you can then ignore in a special element handler of jsPDF.
Therefore your HTML should look like this:
<!DOCTYPE html>
<html>
<body>
<p id="ignorePDF">don't print this to pdf</p>
<div>
<p><font size="3" color="red">print this to pdf</font></p>
</div>
</body>
</html>
Then you use the following JavaScript code to open the created PDF in
a PopUp:
var doc = new jsPDF();
var elementHandler = {
'#ignorePDF': function (element, renderer) {
return true;
}
};
var source = window.document.getElementsByTagName("body")[0];
doc.fromHTML(
source,
15,
15,
{
'width': 180,'elementHandlers': elementHandler
});
doc.output("dataurlnewwindow");
One very important thing to add is that you lose all your style
information (CSS). Luckily jsPDF is able to nicely format h1, h2, h3
etc., which was enough for my purposes. Additionally it will only
print text within text nodes, which means that it will not print the
values of textareas and the like. Example:
<body>
<ul>
<!-- This is printed as the element contains a textnode -->
<li>Print me!</li>
</ul>
<div>
<!-- This is not printed because jsPDF doesn't deal with the value attribute -->
<input type="textarea" value="Please print me, too!">
</div>
</body>
Attach the pdf and send emails with the help of this link
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
Recurly instructions on how to build a form
Github repository that demonstrates the problem.
My form:
<form id="recurly_form">
<div data-recurly="number"></div>
<div data-recurly="month"></div>
<div data-recurly="year"></div>
<div data-recurly="cvv"></div>
<button onClick={this.handleFormSubmit} >
Place order
</button>
</form>
I make every attempt to make sure the configure call is made after everything is mounted and ready:
componentDidMount() {
$(() => {
window.recurly.configure({
publicKey: "ewr1-xxxxxxxxxxxxxxxxx"
});
});
}
The end result is a tall blank screen with a button:
Markup looks like this:
Note that the month field is set to visibility:hidden. Also note that the <div data-recurly="number"></div> is empty. That is the result of me trying to style it with the styles offered in the instructions.
Please advise on what's missing.
I am playing with readymade code in my squarespace website. I found a way to upload files to my google drive by setting up a readymade google apps script. It works fine on the url given by publishing the app.
However i implemented the html code from the readymade solution on my squarespace page by code injection and it obviously doesn't work. Probably there is no info in the script code that leads to the particular URL generated by publishing the app.
This is the code i use for injection in squarespace (i need some code that connects me to the google app script server side)
<div align="center">
<table width="459" border="0">
<tbody>
<tr>
<td width="462"><div align="center">
<hr>
</div>
<form id="myForm" align="center">
<input type="text" name="myName" placeholder="Your name..">
<input type="file" name="myFile">
<input type="submit" value="Upload File"
onclick="this.value='Uploading..';
google.script.run.withSuccessHandler(fileUploaded)
.uploadFiles(this.parentNode);
return false;">
</form>
<div id="output"></div>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
<style>
input { display:block; margin: 20px; }
</style>
<hr></td>
</tr>
</tbody>
</table>
<h3> </h3>
<p> </p>
</div>
Now here is what the code on server side looks like:
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('form.html');
}
function uploadFiles(form) {
try {
var dropbox = "RHT";
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var blob = form.myFile;
var file = folder.createFile(blob);
file.setDescription("Uploaded by " + form.myName);
return "File uploaded successfully " + file.getUrl();
} catch (error) {
return error.toString();
}
}
Please help this must be very simple code to add to make it work.
Thanks a lot
You can now do this by changing the first few lines of your Google Script to the following;
function doGet() {
return HtmlService.createHtmlOutputFromFile('index.html').setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}
Then you can either add a Code Block into Squarespace and an iframe, or I have mine located under the Advanced tab of a Form Block, in the POST-SUBMIT HTML section (users fill out my form first, then are able to upload their content with the script) I use this code, but you can adjust the widths or whatnot;
<iframe src="https://YourPublishedGoogleScriptURLhere"width="625"height="361"frameborder="0"></iframe>
I have this same issue. I believe the issue is that Google is blocking us from using the script in iframes and such, outside of their domain. My current solution is to
Create a Form in Squarespace
Enter required information into the "fields"
In the Advanced tab, insert code obtained from http://www.squareguru.com/form-redirect which will automatically redirect users to your Google Script. The code looks like this;
<meta http-equiv="refresh" content="0; url=https://script.google.com/macros/s/etc">
<script>
window.location.href = 'https://script.google.com/macros/s/etc';
window.location.assign('https://script.google.com/macros/s/etc');
</script>
In my Google Script "server.gs" page, I just changed the line return "File uploaded successfully " + file.getUrl(); to return "File uploaded successfully. Please click the back button in your browser to return to Site Name";
If anyone knows how to have a Google Apps Script redirect to another URL after it is completed instead of displaying "File uploaded successfully", then I could have it redirect to a page on my site which says the upload completed successfully and to continue looking at our other blogs, etc.
I'm also testing out jotform.com which lets you do file uploads into Google Drive in their forms, but they charge a monthly fee unless their free tier covers your needs. They then give you the code to insert the form into Squarespace.
Hope this was helpful. If anyone has ideas to redirect to another URL after the Google Apps Script completes, please let me know.
EDIT: I imagine you would also need this <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> which is placed in Advanced > Code Injection > Header, to allow the script run.