How do I catch an invalid API key for google maps - javascript

I have this code:
<script src="http://maps.google.com/maps?file=api&v=2&sensor=false&key=babab" type='text/javascript'></script>
If the key is invalid then it pops up an alert, but I want to perform some action in this case. I'm not sure how to hook into it though. Any ideas?

Google does not offer an external method of checking the Google Maps API key. Hence you cannot query some service with e.g. "Is this code valid abcde1234" and get a TRUE/FALSE response.
There is a discussion on how the Maps API key is generated. But I suggest you look at a post from Mike Williams about the GValidateKey function. This is the function actually doing the magic validation - what it exactly does, like creating a hash from your Google account / domain - we don't know.
I see two solutions for your problem of checking whether the API key provided is correct:
Overwrite the incoming alert with some custom code (check for the content of the alert, or check if an alert occurs withing X seconds after page load)
Somehow get the GValidateKey function to validate your key beforehand. Maybe you can call it before referencing the API Javascript? Sounds kind of hackish to me...
The problem you will likely have is that you don't know what Google actually checks. The referrer, the referring site, the host - many possibilities (it is not the IP address of the server, but the name plus some additional information).

I just ran across the need to perform an action if an invalid API key was used. Google's documentation states:
If you want to programmatically detect an authentication failure (for example to automatically send an beacon) you can prepare a callback function. If the following global function is defined it will be called when the authentication fails.
This was all I needed to do:
function gm_authFailure() { // Perform action(s) }

For modern browsers (IE9+ and others) you may use DOMNodeRemoved event. You just need to add event handler to the element that you pass to the map constructor:
var map = new google.maps.Map(element, myOptions);
element.addEventListener("DOMNodeRemoved", function(e){
if (e.target === element){
//your code here
element.removeEventListener("DOMNodeRemoved", mapWasRemovedHandler, true);
}
}, false);

Related

How to track custom events

I have a form that has multiple drop-downs and a submit button. This form posts via ajax and returns a different result depending on the combination selected in the dropdowns. Assuming I get a desired result, I want to be able to track this combination in analytics.
I would have expected to be able to use a javascript snippet that would allow me to push the custom event, along with the custom parameters, when the ajax result has come back. However I'm finding it very difficult to understand how to do this.
I've taken a look at the GA4 / Tag Manager documentation and I can see how to create the event and parameters, but when it comes to triggers I'm not sure what to do? GA provides the option to create a button click trigger, but I don't want to capture this data when the button is clicked - I only want to capture it when the response is received from the server. Ideally I'd do something like this:
$.post('/my_endpoint',
{
dropdown1: dropdown1_value
dropdown2: dropdown2_value,
dropdown3: dropdown3_value,
dropdown4: dropdown4_value
})
.done(function (response) {
if(<my_condition>) {
// Push to GA with dropdown1_value, dropdown2_value, dropdown3_value, dropdown4_value
}
});
Is there no way via script to push this event with the required parameters? You can see I require the ability to push the event manually, rather than relying on GA's triggers.
I recall in the past I've used dataLayer.push(), however this was years ago and analytics has evolved since I've last used it. I guess I'm trying to find Google Analytics APIs for pushing custom events, or does such a thing no longer exist?
You can do a dataLayer.push() of your parameters and an event like following:
dataLayer.push({'event': 'your-event-name', 'dropdown1_value' : value1, 'dropdown2_value' : value2, ...});
So in Google Tag Manager you have to create a dataLayer variable for how many values of dropdwon you want to pass. Then you have to create a GA4 Tag with the name you want, you enter the parameters with the values you retrieve from the dataLayer variables and as trigger you use an event named 'your-event-name'.

Google Tag Manager Virtual Page View

I have a little problem setting up a virtualPageView which should override the URL which is sent to google when no result is present.
Heres what I have as JavaScript code:
function returnNoSearchResultsGoogleTagManagerCode($searchterm){
if ($searchterm == "") return "";
$requestUri = $_SERVER['REQUEST_URI'] . "&no_result=".$searchterm;
$js = "<script>
$(document).ready(function(){
dataLayer.push({
'event':'empty_result',
'virtualPageURL':'".$requestUri."'
});
});
</script>";
return $js;
}
As you can see, I want to use an event trigger (empty_result).
In google, I use a Trigger to determine if the Page is a no result Page. First i created a custom Variable with custom JS
function(){
if (document.getElementsByClassName('ga-no-result').length > 0){
return true;
}else{
return false
}
}
The class is set, if the SearchEngine can't find a result. So far so good.
I also created a dataLayer variable to hold the virtualPageURL
Now I need an event which is triggered if the variable is true.
Finally I created a Tag with type PageView which is fired when the event occurs:
Until now it seems okay, the Tag is properly configured (i guess) but if I do a search which has no result, the Page URL is not overridden
The Tag is properly fired and the variables are filled. The overview of the dataLayer shows a correct dataLayer event.
But the PageURL is not overridden... Even if I wait a whole day, the category isn't sent to google.
What am I doing wrong?
I would be very thankful if someone would have an idea or even a solution :)
Thanks in advance
exa.byte
UPDATE:
Hey, I forgot to mention, that I want to use the new page variable as the string which google should use to determine the searchterm and the searchcategory
In Google Analytics I configuered the search as the "q" parameter and the "no_result" as the category.
Is it even possible to change the string which google will parse in the end?
To send a virtual pageview to Google Analytics, the field you need to change is page not {{Page Url}} , also the title field is often used.
That's really the only two things you need to do to send a simple virtual pageview.
Extra: I always start my pagepath with /virtual/ to be able to recognize which ones are virtual pageviews easily in GA
For virtual page view you have to change Field "page" - in your GTM-OnSearchEmptyResult you are changing "{{Page URL}}" - I don't think that's correct way to send virutal pageview. Also if you need to change hostname use Fieldname "hostname".
In preview mode you will not see Page URL changed in Variables Tab, you have to go to the actual GA tag that is fired and check it's values. You can either do this in GTM's preview tool or you can use standard developer tools - Network Tab and see what values are being sent to GA:
You can see "dl" parameter is the current page, if you set up virtual page you should also see parameter called "dp" this is going to be the new value of page in your GA.
If you want to setup virtual pageview you have to use page instead of {{Page URL}} in your fieldname and for Document title use title in you fieldname.
for more field reference of google analytics follow below link
https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#hitType.
If you don't want to mess around with custom Tag Manager events it's still possible to use the good old ga method, even if you don't include the Analytics code on the page. You just need to fetch the right tracker dynamically, as explained by Simo Ahava in this thread.
if (typeof ga === "function") {
ga.getAll().forEach((tracker) => {
tracker.set('page', '/my/path'); // <- change here
tracker.send('pageview');
});
}
I also put it in a gist here.
thanks for your help. I think I got rid of the Problem and have solved it now. I will describe my solution below:
The solution is quite simple.
I had an error/ spelling error # google backend. I set the search_category parameter to "no_results", but used "no_result" for implementation...
Pretty dumb, but sometimes you just won't see the wood for the trees...
I created a new Trigger as helper "HelperDomReady" to trigger the only if DOM is ready and the variable "isEmptySearch" equals "(bool)true"
Now I can see the searchterms which have no result in google backend in the "sitesearch categories" summary. Since I won't set the parameter at all, if the search had at least one hit, the site-search category shows "not-set" for successful results. Therfore the category-section will only show searches without a hit. Problem solved :)
Disadvantage: The searchterm is also listed in the normal list. But I think this is negligible

You do not have permission to use copyTo

I'm trying to copy a range from one sheet to another (whilst preserving the formulas). I wrote a simple script using copyTo:
function copyRangeAcrossSheets(source_sheet,source_range,target_sheet,target_range) {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var source_sheet = spreadsheet.getSheetByName(source_sheet);
var target_sheet = spreadsheet.getSheetByName(target_sheet);
var source_range = source_sheet.getRange(source_range);
var target_range = target_sheet.getRange(target_range);
source_range.copyTo(target_range);
}
Which I call as followed:
=copyRangeAcrossSheets("TEST_source","A1:A3","TEST_target","A1:A3")
And I'm getting the below error:
You do not have the permission to call copyTo
I did some digging around and found that functions have to use special triggers (installable) in order to modify another file. However here I'm modifying the same file.
Q1: Why is copyTo failing here?
Q2: How can I workaround the issue without having to define installable triggers? (I just want to copy ranges whilst preserving formulas)
Why is it failing?
You cannot modify other any documents that require authorization via a custom function. The reason for this is that your function is executed as an anonymous user, which cannot obtain the necessary authorization to edit other sheets or documents of yours.
Reference: https://developers.google.com/apps-script/guides/sheets/functions#using_apps_script_services
Specific to you is this snippet:
Spreadsheet: Read only (can use most get*() methods, but not set*()).
Cannot open other spreadsheets (SpreadsheetApp.openById() or SpreadsheetApp.openByUrl()).
Also:
If your custom function throws the error message "You do not have permission to call X service.", the service requires user authorization and thus cannot be used in a custom function.
How can you work around this?
Write an Apps Script function that is executed via a trigger or manually, you can use onEdit or onChange triggers, or a time-based trigger. You can even manually run the function in the Apps Script IDE when you need to. This is the intended behavior of Apps Script.
Not sure about whether or not your data is persistent in your source spreadsheet, but you could always use the built-in IMPORTRANGE() function. Syntax is:
=IMPORTRANGE("SPREADSHEET_ID","SOURCE_SHEET!RANGE_START:RANGE_END")
Where SPREADSHEET_ID is the ID of the file you're working on.

Google Tag Manager - read cookie just after they are set

I need to read cookie that are set by Google Tag Manager.
Right now if Google Tag Manager is loaded first time for end-user I can't read cookies (because it happens later, but not immediately).
Is there a good way (callback?) that can help me to read cookies once they are set? This issue is only relevant if user visits page first time.
From the discussion in the comments below the question, I would suggest the following solution (assuming you also send Pageviews to Google Analytics). Examples are based on Simo Ahava's (excellent) blog.
(Please note that I haven't had the opportunity to test it thoroughly, as I am currently unable to create a complete test case for this setup -- there might be some hiccups)
1. Create a Variable to read the _ga cookie
Reference: https://www.simoahava.com/analytics/macro-magic-google-tag-manager/#1-client-time
This will return the value for the cookie with name specified (be careful in where you use the value read, as there is always a chance that cookies are rejected by the User's browser policies).
Create a new Variable, with:
Variable Name of GA Cookie
Cookie Name of _ga
(source: simoahava.com)
2. Define a callBackFunction
Reference: https://www.simoahava.com/analytics/macro-magic-google-tag-manager/#8-hitcallback-with-a-universal-analytics-tag & https://www.simoahava.com/analytics/macro-magic-google-tag-manager/#6-get-clientid-using-_ga-cookie
This callback function will be executed right after the Pageview is sent (i.e. after the _ga cookie is set).
Create a Custom JavaScript Macro with the following code:
function () {
return function () {
// Code to be executed in order to read the cookie:
try {
var gaCookie = {{GA Cookie}};
// Do what you need to with the cookie here:
// ...
return gaCookie;
} catch (e) {
console.log('No Universal Analytics cookie found.');
return 'N/A';
}
}
}
3. Define a hitCallback after sending the Pageview
Reference: https://www.simoahava.com/analytics/macro-magic-google-tag-manager/#8-hitcallback-with-a-universal-analytics-tag
This will execute the callback function you just defined right after the Pageview is sent.
In the Fields to set option of your Pageview Tag, set:
Field Name to hitCallback
Value to {{callBackFunction}}
Hope it can help you move forward.

Determine if Google Maps API is using an invalid key during runtime

I'm looking for a way to determine whether a valid Google maps API key is being used. Using an invalid key, we receive an error stating that the google API has been disabled. I'd like to capture that return, and determine whether or not to do our geocoding functions based on that return.
As it stands, when we save a record, we look to see if the address has been changed. If it has, we get the geocode of that address, and after the success/failure message has been passed back, we continue on with our processing before we save the record.
When the API is disabled, the code simply stops. Nothing is returned - no success or failure. At this point, our code stops as well as we rely on the return so we know where to go from there. We are not looking for a way to get around licensing, simply a way to determine whether the API is disabled at runtime. Any ideas?
Well there's something i found in Web > Maps JavaScript API > Events under title "Listening for authentication errors"
If you want to programmatically detect an authentication failure (for
example to automatically send an beacon) you can prepare a callback
function. If the following global function is defined it will be
called when the authentication fails.
so you just need to define a global function:
function gm_authFailure() { /* Code */ };
Unfortunately there is no implemented option to detect a disabled API.
Last year I've made a feature-request , but I don't think that something will happen.
two possible options(there may be more):
when you use a map usually the API first will try to create the map(some elements will be added to the map-container ). When the API will be disabled, these elements will be removed. So you may do something when this happens(e.g. set a variable that indicates the disabled-status):
document.getElementById('map-canvas')//map-container
.addEventListener ('DOMNodeRemoved', function(e){
if(!this.children.length){
alert('the API has been disabled');
if(window.google && window.google.maps){
window.google.maps.disabled=true;
}
}
}, false);
override the alert-method to intercept the particular message:
(function(f){
window.alert=function(s){
if(s.indexOf('Google has disabled use of the Maps API for this application.')
===0){
if(window.google && window.google.maps){
window.google.maps.disabled=true;
alert('the API has been disabled');
return;
}
}
f(s);
}
})(window.alert)
In both cases you may later use the (custom)disabled-property of google.maps to check if the API has been disabled:
if(google.maps.disabled===true){
//execute alternative code
}

Categories

Resources