I am trying to simply get the Google sign-in button working on my website, but I am stuck at the following step:
Getting profile information
As you can see, Google has taken an extremely straightforward task and made it impossible with contextless code snippets, and I am absolutely stuck. Right now, all I have done is put the following in the head of my HTML file:
<script src="https://apis.google.com/js/platform.js" async defer></script>
<meta name="google-signin-client_id" content="(I PUT MY CLIENT ID HERE ALREADY).apps.googleusercontent.com">
All I want to do is sign the user in WITHOUT requesting email address. My problem is the following:
WHERE do I put the gapi.load('auth2', function()... code snippet? At the top level of my webpage's JavaScript file? In the body's onload function? In the onSignIn function? NONE of the above are working. I get an exception, or it says "gapi is not defined" or it says "auth2 is not defined" etc... And once that code snippet is in place, where do I put the if (auth2.isSignedIn.get()) code snippet? You'd think the geniuses at google would think to include this incredibly simple, vital information in their tutorial. Incredibly frustrating.
You can pass the url a callback function to be run when the javascript gets loaded.
<script src="https://apis.google.com/js/platform.js?onload=googleLoaded" async defer></script>
So in your code you can do
function googleLoaded(){
// The script is ready to use.
// gapi.load('auth2', function()...
}
found here https://developers.google.com/identity/sign-in/web/build-button
Related
I am trying to add Google Analytics to our website using the gtag API.
Most of the events I am interested in happen in our PHP code, so I collect them in the session and inject them into the next page that renders. This allows me to handle eg. a login followed by a redirect to the home page.
However, when I try and load the page, none of the injected events are triggered.
I know the system works as I can bind a 'gtag' call to a button's onClick event and it works when I click it, but the automatic ones don't.
Here is an example file: test.php:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test Analytics</title>
</head>
<body>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script type="text/javascript">
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
// First attempt: Added to the datalayer with the rest of the config.
gtag('event', 'test-event-1');
// Second attempt: Added once everything has finished loading.
window.addEventListener('load', function () {
gtag('event', 'test-event-2');
})
</script>
<div class="container">
<h1>This is a test</h1>
<p>Click to trigger another event.</p>
<!-- Successful attempt: Event is triggered when run from a button event handler. -->
<button type="button"
onclick="gtag('event', 'test-event-3')">
Send Event
</button>
</div>
</body>
</html>
When I open this page with Firefox's Network tab running and click the button, I can see the following URLs sent:
GET "http://testapp.localhost:9009/analytics-test.html",
GET "https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX",
GET "http://testapp.localhost:9009/favicon.ico",
POST "https://region1.google-analytics.com/g/collect?v=2&tid=G-XXXXXXXXXX>m=2oeav0&_p=22328352&cid=1447481123.1666024506&ul=en-us&sr=1920x1080&_s=2&sid=1667482491&sct=17&seg=1&dl=http%3A%2F%2Ftestapp.localhost%2Fanalytics-test.html&dt=Test%20Analytics&en=user_engagement&_et=4840",
POST "https://region1.google-analytics.com/g/collect?v=2&tid=G-XXXXXXXXXX>m=2oeb20&_p=1344830813&cid=1447481123.1666024506&ul=en-us&sr=1920x1080&sid=1667482491&sct=17&seg=1&dl=http%3A%2F%2Ftestapp.localhost%2Fanalytics-test.html&dt=Test%20Analytics&_s=1",
POST "https://region1.google-analytics.com/g/collect?v=2&tid=G-XXXXXXXXXX>m=2oeb20&_p=1344830813&cid=1447481123.1666024506&ul=en-us&sr=1920x1080&_s=2&sid=1667482491&sct=17&seg=1&dl=http%3A%2F%2Ftestapp.localhost%2Fanalytics-test.html&dt=Test%20Analytics&en=test-event-3&_ee=1&_et=14263",
The 'en' is the event name, so you can see that only 'test-event-3' is sent to Google.
Please can you let me know how to change the code so that 'test-event-1' and 'test-event-2' are sent to Google as well?
Ok, many issues, but the most likely issue here is that your config happens before the library is loaded. Move your gtag config to the window load. Gtag may not be smart enough to retroactively inspect the dataLayer.
Another issue here is that you seem to be looking at the network tab. There's a way easier way to debug analytics. I suggest trying the Adswerve debugger extension. It shows your events in a much easier to look at presentation right in the console:
Good. Another issue here is that you're editing a php file. This kind of implementation is being frowned upon by the industry. There are many problems around implementing tracking in backend files. Implementing it in the template files would be a bit better, but still quite a poor design.
The proper implementation would be using GTM. GTM would handle retroactive datalayer pushes better, but you would also likely not need them with GTM. GTM is basically a script that is able to intelligently load other scripts whenever is required and translate business-like logic set via its UI to code. So with GTM, you just load it on every page and the rest of the tracking is done in its interface.
While doing gtag calls manually is a way to implement tracking, it's like making a site with no web-server, just quickly deploying your own backend network listeners that would spew html in response. A very odd and niche choice not making sense in vast majority of cases. Don't expect this kind of tracking to live long, to be appreciated, to be scalable or manageable or even to be very useful. Not a great legacy either.
I have a library with HTML-form like this:
code.gs:
function openDialog() {
SpreadsheetApp.getUi().showModalDialog(HtmlService.createHtmlOutputFromFile("h"), "Test" );
}
function hello() {
console.log('booo');
}
h.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<button id="b">Click me</button>
<script>
var b = document.getElementById('b');
b.onclick = function() {
google.script.run
.withSuccessHandler(function(str){window.alert("executed");})
// .withFailureHandler(function(error){window.alert("failed");})
.hello();
}
</script>
</body>
</html>
I shared this script for view and deployd it as a library. Next I created a bound script in Google Sheet with this code:
function onOpen() {
SpreadsheetApp.getUi().createMenu('test').addItem('run', 'myFunction').addToUi();
}
var hello = function() {};
function myFunction() {
TT.openDialog();
}
I've added the library with identifier: TT.
Next I refreshed my Google Sheet file with bound code to see the menu "test", ran test > run. The HTML-window appeared. When I clicked the button, nothing happened. When I opened console, I saw the error:
This error does not appear if I do not use library.
I have experienced the same situation with you. In my case, the reason of the issue was due to the authorization at the library side.
When the authorization process for using the scopes in the library is NOT done at the library side, I confirmed that the error of Uncaught occurred.
When the authorization process for using the scopes in the library is done at the library side, I confirmed that the error of Uncaught didn't occur.
Namely, in my environment, I confirmed that when the library is used for your situation, it was required to authorize the scopes for both the client side and the library side.
So, as a workaround, I used the following flow.
Workaround:
Create a Google Apps Script library.
Please copy and paste your script of code.gs and h.html to the standalone script or the container-bound script.
Deploy the Google Apps Script as the library.
In your script, for example, please directly run hello() at the library side, and authorize the scopes.
Install the library to the client side and load the library from the client side.
Please run myFunction() at the client side.
By this flow, when you run run at the custom menu and click the button, the dialog of executed is opened.
Note:
In this case, when I wanted to make users use the client script, it was required to authorize the scopes for both the client side and the library side. I thought that this may be a little inconvenient.
So, how about reporting this for the Google issue tracker? Ref Unfortunately, I couldn't find the issue tracker with the same situation.
Added:
As the method for authorizing the scopes at the library side from the client side, I would like to propose to use Web Apps. I thought that when the Web Apps is used, the authorization of the library side can be done at the client side. By this, I thought that the inconvenience may be resolved a little.
Please do the following flow.
1. Library side.
Please copy and paste the following scripts.
Google Apps Script: code.gs
function openDialog() {
SpreadsheetApp.getUi().showModalDialog(HtmlService.createHtmlOutputFromFile("h"), "Test" );
}
function hello() {
console.log('booo');
}
function doGet() {
return HtmlService.createHtmlOutput("ok");
}
HTML: h.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<button id="b">Click me</button>
<script>
var b = document.getElementById('b');
b.onclick = function() {
google.script.run
.withSuccessHandler(function(str){window.alert("executed");})
// .withFailureHandler(function(error){window.alert("failed");})
.hello();
}
</script>
</body>
</html>
2. Deploy Web Apps at library side.
Please deploy Web Apps at the library side. About the method for this, you can see the official document. Ref The detail setting is as follows.
Execute as: User accessing the web app
Who has access: Anyone with Google account
3. Deploy as library.
Please deploy as the library. Ref
4. Client side.
Please install the library to the client side. And, please copy and paste the following scripts. In this case, please replace https://script.google.com/macros/s/###/exec with your Web Apps URL.
function onOpen() {
SpreadsheetApp.getUi().createMenu('test').addItem('auth', 'auth').addItem('run', 'myFunction').addToUi();
}
var hello = function() {};
function myFunction() {
TT.openDialog();
}
function auth() {
const html = HtmlService.createHtmlOutput(`<input type="button" value="Authorize" onclick="window.open('https://script.google.com/macros/s/###/exec', '_blank');google.script.host.close()">`);
SpreadsheetApp.getUi().showDialog(html);
}
5. Testing.
At first, please run auth at the custom menu. By this, you can authorize the scopes of both the client side and the library side. When the new tab is not opened when auth is run, please run auth() at the script editor again.
As the next step, please run run. By this, your dialog is opened. And, when both authorizations (client and library side) with auth has already been finished, when you click the button, the dialog of executed is opened.
References:
Web Apps
Taking advantage of Web Apps with Google Apps Script
Something I've recently done on a few sites I've developed for is to create an included JavaScript function which prints an email address based off of an argument. An example below:
/index.html
...
<head>
<script src="/script/main.js></script>
</head>
<body>
...
<p><script>printEmail('info');</script></p>
...
/script/main.js
function printEmail(a) {
document.write('' + a + '#domain.com');
}
The thought process that I have is that the relatively small script should help deter spambots by not including the email address in full anywhere in the source code. The only place it becomes readable is through the rendering engine.
So is it secure? Also, how secure is it compared to other prevention methods?
If it renders to the page on page load, I don't think this would do anything, since the spam bots would wait for the page to load anyways and then grab the emails.
If you make a user action required, like hovering over the email to reveal the full email, at which point the javascript prints it out, I think that would be more effective, and I've seen things like that in use on pages before.
I have a Google +1 button on my site that requires the following script:
<script src="https://apis.google.com/js/platform.js" async defer></script>
The problem is as of today, apis.google.com can't be pinged from everywhere (servers are down) and some of my users don't see a button. I don't always want to use my own copy of the script because I can see that breaking the +1 functionality at some point. I'd like to use something like the solution from this question: my server's fallback copy should be fetched only when the CDN fails.
What's a good way to do that for this script? Is there a generic way to do this for any remote script using jQuery or plain js? Thanks in advance.
EDIT:
I tried jQuery getScript() and wrapped it in a function like this:
function fetch_script(script,fallback) {
$.getScript( script )
.fail(function() {
$.getScript( fallback );
});
};
This does not always work and is not reliable. Two problems I found:
500 errors trigger the fail method, but 404 errors do not and the fallback script is not loaded in these cases. Not sure what happens if the server is just down.
Some scripts are fetched (I see this in the console) but are somehow not executed (or they fail silently). Here's a script that doesn't work.
Intro: I'm having a problem implementing google analytics in a website that is not mine and would like to correctly implement it and confirm without the need of waiting several hours untill google checks my website again.
Main problem: I copy pasted the script code to every page on the website (all html) but google isn't detecting it. I suspect the problem is in the first index.html on the root of the website but for now I must have it there so please don't tell me I have to remove this file. That is not the question.
Code of index.html:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<script>
<!-- GOOGLE ANALYTICS PASTED CODE IS HERE -->
</script>
<!-- TITLE AND METADATA ARE HERE BUT NOT RELEVANT -->
<meta http-equiv="REFRESH" content="0;url=http://www.FAKEDOMAIN.com/Site/index.html">
</head>
<body>
</body>
</html>
Extra info: Google control not installed because it says it doesn't detectes the code on initial page. I think it is because the script might not be tottaly executed and then the page refreshs to another link and google will just consider that the script isn't installed on the initial page because the script wasn't tottaly run. Is there a way I can force the full execution before redirecting? Then a way to confirm with alerts if the data is being collected properly so that I am sure it is just a matter of time before google analytics control is properly installed?
I don't believe Google actually attempts to detect the code on your page. Rather, the page runs and the script executes and pings some Google server to report the usage. Once this usage gets reported, you'll start seeing activity in your Google account. This might take a day or two.
I think you're right about the meta refresh though. Once the meta tag is encountered, the browser will redirect and script on the page is not executed. I would suggest removing the <meta> tag and redirecting with script, after the Google Analytics code is run:
<script>
// GA code here
location.href = 'http://www.FAKEDOMAIN.com/Site/index.html'; //Redirect here
</script>