Google Universal Analytics has a hit type of exception
ga('send', 'exception', {
'exDescription': 'DatabaseError'
});
I was expecting to be able to just go to the Google Analytics console and find an exeption report at the same level as 'events' however it's nowhere to be seen.
The Android and iOS APIs say Crash and exception data is available primarily in the Crash and Exceptions report but I can't find any report by that name.
Figured it out. I'm not sure why they don't make this a built in report but maybe someday.
I made a custom widget in a dashboard with Exception Description for dimension and 'Crashes' for the metric:
Which gives me a report like this:
You can also go to Customization tab and create a custom report to give you a table of errors, and then add it to your dashboard.
Used with this global exception handler
if (typeof window.onerror == "object")
{
window.onerror = function (err, url, line)
{
if (ga)
{
ga('send', 'exception', {
'exDescription': line + " " + err
});
}
};
}
You can put this handler anywhere in the initialization of your Javascript - which will depend upon how you have all your JS files configured. Alternatively you can just put it inside a <script> tag near the top of your html body tag.
I took Simon_Weaver's guide to making a custom report a few steps further and built out a fairly complete Google Analytics custom exceptions report. I figured it might be worth sharing, so I uploaded it to the GA "Solutions Gallery".
My template: Google Analytics Exceptions Report
Here's a picture of the end result:
I just wanted to expand a bit on #Simon_Weaver 's excellent answer to provide error reports with a few additional details:
Make sure ga() is defined before trying to call it (as an Error could be triggered before the Analytics library is loaded).
Log Exception line numbers and column index in the Analytics Reports (although minified JavaScript code used in production might be difficult to read).
Execute any previously-defined window.onerror callback.
/**
* Send JavaScript error information to Google Analytics.
*
* #param {Window} window A reference to the "window".
* #return {void}
* #author Philippe Sawicki <https://github.com/philsawicki>
*/
(function (window) {
// Retain a reference to the previous global error handler, in case it has been set:
var originalWindowErrorCallback = window.onerror;
/**
* Log any script error to Google Analytics.
*
* Third-party scripts without CORS will only provide "Script Error." as an error message.
*
* #param {String} errorMessage Error message.
* #param {String} url URL where error was raised.
* #param {Number} lineNumber Line number where error was raised.
* #param {Number|undefined} columnNumber Column number for the line where the error occurred.
* #param {Object|undefined} errorObject Error Object.
* #return {Boolean} When the function returns true, this prevents the
* firing of the default event handler.
*/
window.onerror = function customErrorHandler (errorMessage, url, lineNumber, columnNumber, errorObject) {
// Send error details to Google Analytics, if the library is already available:
if (typeof ga === 'function') {
// In case the "errorObject" is available, use its data, else fallback
// on the default "errorMessage" provided:
var exceptionDescription = errorMessage;
if (typeof errorObject !== 'undefined' && typeof errorObject.message !== 'undefined') {
exceptionDescription = errorObject.message;
}
// Format the message to log to Analytics (might also use "errorObject.stack" if defined):
exceptionDescription += ' # ' + url + ':' + lineNumber + ':' + columnNumber;
ga('send', 'exception', {
'exDescription': exceptionDescription,
'exFatal': false, // Some Error types might be considered as fatal.
'appName': 'Application_Name',
'appVersion': '1.0'
});
}
// If the previous "window.onerror" callback can be called, pass it the data:
if (typeof originalWindowErrorCallback === 'function') {
return originalWindowErrorCallback(errorMessage, url, lineNumber, columnNumber, errorObject);
}
// Otherwise, Let the default handler run:
return false;
};
})(window);
// Generate an error, for demonstration purposes:
//throw new Error('Crash!');
Edit: As #Simon_Weaver duly noted, Google Analytics now has documentation about Exception Tracking (which I should have linked to in my original answer -- sorry, rookie mistake!):
https://developers.google.com/analytics/devguides/collection/analyticsjs/exceptions
https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#exception
This is what I came up with so you don't need to include the code everywhere. Just add new ErrorHandler(); to each .js file. This was done for a Chrome Extension, but should work anywhere, I think. I implement the actual ga() stuff in a separate file (hence the app.GA), but you could bake it in here too.
/*
* Copyright (c) 2015-2017, Michael A. Updike All rights reserved.
* Licensed under the BSD-3-Clause
* https://opensource.org/licenses/BSD-3-Clause
* https://github.com/opus1269/photo-screen-saver/blob/master/LICENSE.md
*/
// noinspection ThisExpressionReferencesGlobalObjectJS
(function(window, factory) {
window.ExceptionHandler = factory(window);
}(this, function(window) {
'use strict';
return ExceptionHandler;
/**
* Log Exceptions with analytics. Include: new ExceptionHandler();<br />
* at top of every js file
* #constructor
* #alias ExceptionHandler
*/
function ExceptionHandler() {
if (typeof window.onerror === 'object') {
// global error handler
window.onerror = function(message, url, line, col, errObject) {
if (app && app.GA) {
let msg = message;
let stack = null;
if (errObject && errObject.message && errObject.stack) {
msg = errObject.message;
stack = errObject.stack;
}
app.GA.exception(msg, stack);
}
};
}
}
}));
You can now find a "Crashes and Exceptions" view under Behavior (if property is created as a "mobile app" in Google Analytics).
Related
I am attempting to implement the Revit to Excel exporter discussed here. The button is working and passing urn and token to
ForgeXLS.downloadXLSX(urn, token, callback /*Optional*/);
I receive an error" "GET " 403 (forbidden)"
I am extending the Extensions Skeleton tutorial found here.
Is it possible that there is an issue with the scopes... if so can you guide me as to how to adjust the scope of the access token I am pulling?
Code for ForgeXLSX.downloadXLSX is:
downloadXLSX: function (urn, token, status) {
var fileName = decodeURIComponent(atob(urn).replace(/^.*[\\\/]/, '')) + '.xlsx';
if (fileName.indexOf('.rvt') == -1) {
if (status) status(true, 'Not a Revit file, aborting.');
return;
}
if (status) {
status(false, 'Preparing ' + fileName);
status(false, 'Reading project information....');
}
this.prepareTables(urn, token, function (tables) {
if (status) status(false, 'Building XLSX file...');
var wb = new Workbook();
jQuery.each(tables, function (name, table) {
if (name.indexOf('<')==-1) { // skip tables starting with <
var ws = ForgeXLS.sheetFromTable(table);
wb.SheetNames.push(name);
wb.Sheets[name] = ws;
}
});
var wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: true, type: 'binary'});
saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), fileName);
if (status) status(true, 'Downloading...');
})
},
Scope wise, you will need both data:read bucket:read to have sufficient access to model metadata:
Token with insufficient scope ends up with a 403:
Make sure your server sets scope up properly in the request body to fetch access tokens.
And your best bet to observe the URN and Token variables in the process of calling the Forge endpoints is here at ForgeXLS.forgeGetRequest:
After digging around a bit (and some help from a friend) figured out that it was the scopes after all. Adding 'data:read' scope to the public scope in the config.js file provided the needed access and the exporter now works.
scopes: {
// Required scopes for the server-side application
internal: ['bucket:create', 'bucket:read', 'data:read', 'data:create', 'data:write'],
// Required scope for the client-side viewer
public: ['viewables:read', 'data:read']
}
I am kind of new to javascript and building websites, I program c# most of the times.
I am trying to build something and I need to use google translate api, the problem that is cost money so I prefer use Free API so I found this.
https://ctrlq.org/code/19909-google-translate-api
so I changed it a bit and tried alone, because I wasn't sure what e type ment.
so this is my code:
function doGet(text) {
var sourceText = text;
var translatedText = LanguageApp.translate('en', 'iw', sourceText);
var urllog = "https://translate.googleapis.com/translate_a/single?client=gtx&sl="
+ "en" + "&tl=" + "iw" + "&dt=t&q=" + encodeURI(text);
var result = JSON.parse(UrlFetchApp.fetch(urllog).getContentText());
translatedText = result[0][0][0];
console.log(translatedText);
}
so the url is downloading me a text file called "f.txt" that include the translate code the problem is that I doesnt want it to download File,
I just need the translate inside the txt file its gives me,
also the problem is I am not sure how to get that info inside a javascript variable, And I doesnt want it to give me that file as well..
So how Can I read it?
how can I use the file without download it, and How can I push it to a string variable?
And How I can cancel the download and get only the translate?
THANKS!
By the way
and if anyone know the function doGet(e) that I showed on the link, what is "e"? what does the function wants?
I know I'm a year late but I came to same problem and fixed it using PHP. I have created this simple PHP function:
function translate($text, $from, $to) {
if($text == null)
echo "Please enter a text to translate.";
if($from == null)
$from = "auto";
if($to == null)
$to = "en";
$NEW_TEXT = preg_replace('/\s+/', '+', $text);
$API_URL = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=" . $from . "&tl=" . $to . "&dt=t&q=" . $NEW_TEXT;
$OUTPUT = get_remote_data($API_URL);
$json = json_decode($OUTPUT, true); // decode the JSON into an associative array
$TRANSLATED_OUTPUT = $json[0][0][0];
echo $TRANSLATED_OUTPUT;
}
Example usage (English to Spanish):
translate("Hello", "en", "es"); //Output: Hola
/*
sourceLanguage: the 2-3 letter language code of the source language (English = "en")
targetLanguage: the 2-3 letter language code of the target language (Hebrew is "iw")
text: the text to translate
callback: the function to call once the request finishes*
* Javascript is much different from C# in that it is an asynchronous language, which
means it works on a system of events, where anything may happen at any time
(which makes sense when dealing with things on the web like sending requests to a
server). Because of this, Javascript allows you to pass entire
functions as parameters to other functions (called callbacks) that trigger when some
time-based event triggers. In this case, as seen below,
we use our callback function when the request to google translate finishes.
*/
const translate = function(sourceLanguage,targetLanguage,text,callback) {
// make a new HTTP request
const request = new XMLHttpRequest();
/*
when the request finishes, call the specified callback function with the
response data
*/
request.onload = function() {
// using JSON.parse to turn response text into a JSON object
callback(JSON.parse(request.responseText));
}
/*
set up HTTP GET request to translate.googleapis.com with the specified language
and translation text parameters
*/
request.open(
"GET",
"https://translate.googleapis.com/translate_a/single?client=gtx&sl=" +
sourceLanguage + "&tl=" + targetLanguage + "&dt=t&q=" + text,
true
);
// send the request
request.send();
}
/*
translate "This shouldn't download anything" from English to Hebrew
(when the request finishes, it will follow request.onload (specified above) and
call the anonymous
function we use below with the request response text)
*/
translate("en","iw","This shouldn't download anything!",function(translation) {
// output google's JSON object with the translation to the console
console.log(translation);
});
I am very simply trying to print some content in a Windows 10 app (Universal) using HTML and JavaScript/WinJS.
ALL of the documentation says that there is a function on MSApp called getHtmlPrintDocumentSource.
I do not have this, nor can I seem to find any relevant source to see if it may have been moved. I instead have getHtmlPrintDocumentSourceAsync. This seems to be a replacement for the former, but I cannot get it to work and there is zero documentation on it as far as I can tell.
When I run the below code (which is based on the documentation but updated to be async):
function onPrintTaskRequested(printEvent) {
var printTask = printEvent.request.createPrintTask("Print Sample", function (args) {
MSApp.getHtmlPrintDocumentSourceAsync(document)
.then(function(result) {
args.setSource(result);
});
printTask.oncompleted = onPrintTaskCompleted;
});
}
result is populated with some of the print settings as I would expect, but the content property is set to 0, which I am guessing is the problem. I can't really be sure as there is no documentation for this function. I can't even run any of the dozens of pieces of example code in the documentation using `getHtmlPrintDocumentSource' because it seemingly doesn't exist anymore.
In addition to just sending document to the Async method, I have tried a couple of different variations of creating document fragments. Same results.
Probably not terribly helpful, but the message in the Windows Print Dialog that opens when executing the above code is: "Nothing was sent to print. Open a document and print again."
Any ideas?
getHtmlPrintDocumentSource is a synchronous deprecated API in Windows 10 apps. We'll work on some of the docs left behind for Windows 8 and 8.1 to clarify that.
Check out https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/Printing/js for an example of how to use getHtmlPrintDocumentSourceAsync in JavaScript.
Here is the code:
// Needs to be invoked before calling the print API
function registerForPrintContract() {
var printManager = Windows.Graphics.Printing.PrintManager.getForCurrentView();
printManager.onprinttaskrequested = onPrintTaskRequested;
console.log("Print Contract registered. Use the Print button to print.", "sample", "status");
}
// Variable to hold the document source to print
var gHtmlPrintDocumentSource = null;
// Print event handler for printing via the PrintManager API.
function onPrintTaskRequested(printEvent) {
var printTask = printEvent.request.createPrintTask("Print Sample", function (args) {
args.setSource(gHtmlPrintDocumentSource);
// Register the handler for print task completion event
printTask.oncompleted = onPrintTaskCompleted;
});
}
// Print Task event handler is invoked when the print job is completed.
function onPrintTaskCompleted(printTaskCompletionEvent) {
// Notify the user about the failure
if (printTaskCompletionEvent.completion === Windows.Graphics.Printing.PrintTaskCompletion.failed) {
console.log("Failed to print.", "sample", "error");
}
}
// Executed just before printing.
var beforePrint = function () {
// Replace with code to be executed just before printing the current document:
};
// Executed immediately after printing.
var afterPrint = function () {
// Replace with code to be executed immediately after printing the current document:
};
function printButtonHandler() {
// Optionally, functions to be executed immediately before and after printing can be configured as following:
window.document.body.onbeforeprint = beforePrint;
window.document.body.onafterprint = afterPrint;
// Get document source to print
MSApp.getHtmlPrintDocumentSourceAsync(document).then(function (htmlPrintDocumentSource) {
gHtmlPrintDocumentSource = htmlPrintDocumentSource;
// If the print contract is registered, the print experience is invoked.
Windows.Graphics.Printing.PrintManager.showPrintUIAsync();
});
}
The following code displays a proper list of available chromecast devices on my network. But when I click on the links, the application never launches. There are a couple of things that I'm quite confused about that may or may not be related to this question:
If I'm making my own custom application, what's with the DIAL parameters and why do I have to pass them? I don't want to write an app for the DIAL standard... this is MY app.
Again related to the DIAL parameters, if I search for devices with any other query other than "YouTube" (a DIAL parameter), the list always comes up blank. I suppose I shouldn't care, as long as the device is listed... but again... the app won't launch.
It should be noted that my sender app is a chrome webpage.
I'm a bit confused as to where my "appid" goes int he launch parameters,'
<html data-cast-api-enabled="true">
<body>
hi!<BR/>
<script>
var cast_api, cv_activity;
if (window.cast && window.cast.isAvailable) {
// Cast is known to be available
initializeApi();
} else {
// Wait for API to post a message to us
window.addEventListener("message", function(event) {
if (event.source == window && event.data &&
event.data.source == "CastApi" &&
event.data.event == "Hello")
{
//document.write("Initialize via message.<br/>");
initializeApi();
//document.write("Api initialized via message.");
};
});
};
initializeApi = function() {
cast_api = new cast.Api();
cast_api.addReceiverListener("YouTube", onReceiverList);
};
var g_list;
onReceiverList = function(list) {
g_list = list;
// If the list is non-empty, show a widget with
// the friendly names of receivers.
// When a receiver is picked, invoke doLaunch with the receiver.
document.write("Receivers: "+list.length+"<br/>");
var t;
for(t=0;t<list.length;t++)
document.write('found:'+list[t].name+' ' +list[t].id+'<br/>');
};
onLaunch = function(activity) {
if (activity.status == "running") {
cv_activity = activity;
// update UI to reflect that the receiver has received the
// launch command and should start video playback.
} else if (activity.status == "error") {
cv_activity = null;
}
};
function launchy(idx)
{
doLaunch(g_list[idx]);
}
doLaunch = function(receiver) {
var request = new window.cast.LaunchRequest(">>>>>what REALLY goes here?<<<<<<< ", receiver);
request.parameters = "v=abcdefg";
request.description = new window.cast.LaunchDescription();
request.description.text = "My Cat Video";
request.description.url = "http://my.website.get.your.own/chomecast/test.php";
cast_api.launch(request, onLaunch);
};
stopPlayback = function() {
if (cv_activity) {
cast_api.stopActivity(cv_activity.activityId);
}
};
</script>
</body>
</html>
The part marked "what really goes here?" is the part that I THINK is wrong... I couldn't be completely wrong. My device is white listed, I have an appid (which I thought might go in that slot)... The documentation merely says ActivityType DIAL Parmeters are valid, mandatory.
The first argument to the LaunchRequest is your App ID, the one that you have received in an email as part of whitelisting process. Also, the "YouTube" in the initialize method should also be replaced with the same App ID.
I strongly suggest you look at the sample that is on GitHub for chrome sender to see how you can send a request to load a media on a cast device.
i know this question has been asked before but i dont know hwo to make it work.
this is the content script:
console.log("online");
chrome.extension.sendRequest({foo: "yes"}, function(response) {
console.log(response.thefoo);
});
and this is the background page:
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.foo == "yes")
sendResponse({thefoo:"this is the foo"});
else
sendResponse({"it didnt work"});
});
the code that i have here, its from one of the answered questions around here with a few changes that i made, but it didnt work even when i put it exactly.
you can see that answer here Chrome extension: accessing localStorage in content script
---=== background.html ===---
/*
* Handles data sent via chrome.extension.sendRequest().
* #param request Object Data sent in the request.
* #param sender Object Origin of the request.
* #param callbackFunction Function The method to call when the request completes.
*/
function onRequest(request, sender, callbackFunction) {
//your actions here
};
/*
* Add request listener
*/
chrome.extension.onRequest.addListener(onRequest);
---=== contentScript.js ===---
function callbackFunction(response) {
//process the response
}
chrome.extension.sendRequest({'action': 'your action'}, callbackFunction);
you also need to have the content script defined in the manifest file