How to track usage on a node.js RESTful service with Google Analytics? - node.js

I've written a RESTful node.js service as a backend for http://www.cross-copy.net and would like to not only track usage of the web-client but also other clients (like commandline or Apps) which use the service for inter-device copy/paste. Is it possible to embed the Google Analytics JavaScript API into a node.js application and do server-side tracking?

Since all of the answers are really old, I will mention a new npm package:
https://www.npmjs.com/package/universal-analytics
It's really great and incredible easy to use.

Install universal analytics
npm install universal-analytics --save
In your routes file, require the module. (Replace process.env.GA_ACCOUNT with string like 'UA-12345678-1')
// Init GA client
var ua = require('universal-analytics');
var visitor = ua(process.env.GA_ACCOUNT);
Now inside your endpoint functions, you can track a pageview. (Replace request.url with the current url string like '/api/users/1')
// Track pageview
visitor.pageview(request.url).send();
Read the documentation on UA for more info on this module.

As Brad rightfully sad, there was nothing for Node... So I wrote a nodejs module tailored for this these last few days and just published it on NPM: node-ga
The module is still really new (barely trying it in production on a pet project), so don't hesitate to give your input :)

You won't be able to just drop ga.js into your Node project. It has to be loaded in a browser to function correctly.
I don't believe there is anything out there for Node yet (correct me if I'm wrong!), but you should be able to easily adapt the existing PHP classes for doing logging server-side:
https://developers.google.com/analytics/devguides/collection/other/mobileWebsites
You can see how the URL to request the tracking GIF is constructed within ga.php. Translate ga.php to JS and you're set.
$utmGifLocation = "http://www.google-analytics.com/__utm.gif";
// Construct the gif hit url.
$utmUrl = $utmGifLocation . "?" .
"utmwv=" . VERSION .
"&utmn=" . getRandomNumber() .
"&utmhn=" . urlencode($domainName) .
"&utmr=" . urlencode($documentReferer) .
"&utmp=" . urlencode($documentPath) .
"&utmac=" . $account .
"&utmcc=__utma%3D999.999.999.999.999.1%3B" .
"&utmvid=" . $visitorId .
"&utmip=" . getIP($_SERVER["REMOTE_ADDR"]);

I tried out node-ga, but didn't get event tracking to work. nodealytics did the job.

See Core Reporting API Client Libraries & Sample Code (v3).
There is also the following version: Google APIs Client Library for Node.js (alpha).

I wrote a script to query data with Node.js from Googles Analytics Core Reporting API (v3). The script and a detailed setup description is available here.
Here is the script part:
'use strict';
var googleapi = require('googleapis');
var ApiKeyFile = require('mywebsiteGAapi-6116b1dg49a1.json');
var viewID = 'ga:123456700';
var google = getdefaultObj(googleapi);
var Key = getdefaultObj(ApiKeyFile);
function getdefaultObj(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var jwtClient = new google.default.auth.JWT(Key.default.client_email, null, Key.default.private_key, ['https://www.googleapis.com/auth/analytics.readonly'], null);
jwtClient.authorize(function (err, tokens) {
if (err) {
console.log(err);
return;
}
var analytics = google.default.analytics('v3');
queryData(analytics);
});
function queryData(analytics) {
analytics.data.ga.get({
'auth': jwtClient,
'ids': viewID,
'metrics': 'ga:users,ga:pageviews',
'start-date': 'yesterday',
'end-date': 'today',
}, function (err, response) {
if (err) {
console.log(err);
return;
}
console.log(JSON.stringify(response, null, 4));
});
}

Related

Where to Put Google Maps API Key in NodeJS Project

I have Google Maps API Key and want to use it with google-distance-matrix library. But i don't know where to put my Key and integrate it with above stated library here is my code
const distanceAPI = require('google-distance-matrix')
dispatchers.dispatchers.map( (dispatcher) => {
distanceAPI.matrix(dispatcher.location.coordinates, call.pickupLocationCoordinates.coordinates, mode, function(err, distances) {
console.log("distances")
console.log(distances)
})
})
Following error is still being thrown
error = 'You must use an API key to authenticate each request to Google Maps Platform APIs.'
I have also create a variable in .env file with following
G_API = key
Kindly let me know the right way of using the map service.
As mentioned in the README.md of google-distance-matrix you have to precise your key in distance.key() method.
distance.key('myAPIkey');
If your using a .env file you should call your env variable variable with process.env and dotenv package.
index.js :
require('dotenv').config();
const distance = require('google-distance-matrix');
distance.key(process.env.MY_API_KEY);
// Working example code
var origins = ['San Francisco CA'];
var destinations = ['New York NY', '41.8337329,-87.7321554'];
distance.matrix(origins, destinations, function (err, distances) {
if (!err)
console.log(distances);
})
.env :
MY_API_KEY=1234AEB
You can check a full working example on the google-distance-matrix doc
here

Creating an API to wrap an... API?

This isn’t a specific issue question, but I’m trying to wrap my head around the concept of REST APIs and calling an API within your own API.
For example, if I develop an App called “BeesBees”, where users can buy bees, and I have a database of logins and passwords and obviously the bees, and how much each cost, I understand that I can used my own apps BeesBees API to get the list of bees (and if I make it open for other people, they can also use my GET /bees point to get, well, the bees)
But if I want to allow customers to buy the bees, and I don’t want to build a whole platform for doing so, so I integrate Stripe - could I have a POST /:users/charges/:priceOfBee API call that, in turn, called the Stripe API function somewhere somehow? For example, pointing to the URL of a Node.js project that will make the charge using Stripe’s Node.js SDK.
Or, in a case like this, would it be better to just implement the Stripe SDK for my device’s platform and make the charge using the device?
I have no code base so there’s nothing to pick apart, but I couldn’t think of anywhere else to ask, sorry y’all
You can certainly wrap APIs with other APIs, it's really just a form of composition, delegate to other services where it makes sense to do so.
Stripe integration might well be a good example of where it could make sense to follow this pattern. You certainly don't want to roll your own payment service.
Here's a trivial example of a local Express server making an API request:
const express = require("express");
const port = 3000;
const app = express();
const request = require('request');
app.get("/api/example", (req, res) => {
// Make external REST request here...
let options = {
url: 'https://httpbin.org/get',
qs: { parameter1: 42 },
json: true
}
request(options, (err, response, body) => {
if (err) {
res.status(500).send(err.message);
} else {
res.status(200).send(body);
}
});
});
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('running at http://' + host + ':' + port)
});
console.log(`Serving at http://localhost:${port}`);

Unit Testing Azure Mobile App (Node.js) Locally

Please don't tell me I should have been testing before now. I don't disagree, and that's not the point of this question. If it helps, assume I'm doing TDD perfectly and I'm asking this question about a brand new project. ;-)
I've been developing an Azure Mobile App with a Node.js backend for some time now. I have done so completely dependent on Microsoft hosting the service (which I think makes sense). Now, though, I'd like to have some unit tests running against my code, but I'm at a loss for how to get from a functional, Microsoft-hosted Azure Mobile App to a locally-hosted version where I can run my tests.
A big assumption here is that the testing will run much faster if I'm running them locally. A lot of my code interacts with a SQL Server database, so please tell me if this is an incorrect assumption.
Anyway, I've gotten Node.js and NPM set up on my Mac. I've gone through some basic tutorials on creating a Node.js site from scratch, and I got the ubiquitous "Hello World" Node.js website working locally. I even apparently got a basic Azure Mobile site up and running (at least, I got the "This mobile app has been successfully created" homepage to show up).
I've also done some reading on Mocha and Chai for Unit Testing in Node.js. I even got through some of their first examples and had some simple tests working.
What's confusing me is how to move from the super-basic Mocha test examples to more real-world testing of my actual code.
For instance, here's a Mocha test example (taken from semaphore):
var expect = require("chai").expect;
var converter = require("../app/converter");
describe("Color Code Converter", function() {
describe("RGB to Hex conversion", function() {
it("converts the basic colors", function() {
var redHex = converter.rgbToHex(255, 0, 0);
var greenHex = converter.rgbToHex(0, 255, 0);
var blueHex = converter.rgbToHex(0, 0, 255);
expect(redHex).to.equal("ff0000");
expect(greenHex).to.equal("00ff00");
expect(blueHex).to.equal("0000ff");
});
});
describe("Hex to RGB conversion", function() {
it("converts the basic colors", function() {
var red = converter.hexToRgb("ff0000");
var green = converter.hexToRgb("00ff00");
var blue = converter.hexToRgb("0000ff");
expect(red).to.deep.equal([255, 0, 0]);
expect(green).to.deep.equal([0, 255, 0]);
expect(blue).to.deep.equal([0, 0, 255]);
});
});
});
It's no real surprise that this code will fail until ../app/converter.js is created with the appropriate functions exported. Ok, so I try to adapt that kind of thinking to, say, my Login method, and I'm unable to connect the dots.
My Login code happens to reside at ../api/Authentication/Login.js in the file structure. Is that going to matter to my test code, or can I simply reference something like .post('Login')? Either way, here's an overview of my Login.js file:
var auth = require('azure-mobile-apps/src/auth'),
bcrypt = require('bcrypt-nodejs');
module.exports = {
post: function (req, res, next) {
// Actual code removed
}
};
I have no idea how to construct the req, res, and next variables/parameters. When it comes to this point, an article I read by Michael Herman (link) seems to be closer to what I'm trying to do.
In that article, a test-server.js file is set up with contents like this:
var chai = require('chai');
var chaiHttp = require('chai-http');
var server = require('../server/app');
var should = chai.should();
chai.use(chaiHttp);
describe('Blobs', function() {
it('should list ALL blobs on /blobs GET', function(done) {
chai.request(server)
.get('/blobs')
.end(function(err, res){
res.should.have.status(200);
done();
});
});
});
This seems to be referencing /blobs because in ../server/models/blob.js, there is this line:
module.exports = mongoose.model('blobs', blobSchema);
That's what makes me think that maybe the following lines (in my Login.js) are doing something more structured behind the scenes:
module.exports = {
post:
Anyway, this is just the tip of the iceberg. My Azure Mobile App has environment variables and connection strings, etc. Is it possible for me to get all of that running on my local machine, or am I better off to implement my testing in Azure's portal somehow?
If I should do it locally, how can I get that set up?
If I should do it in Azure's portal, how do I begin there?

Examples and documentation for couchnode

I am trying to integrate couchbase into my NodeJS application with couchnode module. Looks like it lacks of documentation. I see a lot of methods with parameters there in the source code but I can't find much information about how they work. Could you please share me with some, may be examples of code? Or should I read about these methods from other languages' documentation as there are chances they are the same?
To make development easier, I wrote a little helper (lib/couchbase.js):
var cb = require('couchbase'),
config;
if(process.env.NODE_ENV === 'production') {
config = require('../lib/config');
} else {
config = require('../lib/localconfig');
}
module.exports = function(bucket, callback) {
config.couchbase.bucket = bucket;
cb.connect(config.couchbase, callback);
};
Here's some example code for a view and async/each get operation. Instead of 'default' you can use different buckets.
var couchbase = require('../lib/couchbase');
couchbase('default', function(error, cb) {
cb.view('doc', 'view', {
stale: false
}, function(error, docs) {
async.each(docs, function(doc, fn) {
cb.get(doc.id, function(error, info) {
// do something
fn();
}
}, function(errors) {
// do something
});
});
});
I adapted an AngularJS and Node.js web application that another developer wrote for querying and editing Microsoft Azure DocumentDB documents to let it work with Couchbase:
https://github.com/rrutt/cb-bread
Here is the specific Node.js module that performs all the calls to the Couchbase Node SDK version 2.0.x:
https://github.com/rrutt/cb-bread/blob/dev/api/lib/couchbaseWrapper.js
Hopefully this provides some help in understanding how to configure arguments for many of the Couchbase API methods.

phonegap webos 3.0+

I have a phonegap iOS app that i ported to webos on the touchpad the app works great except for the one iOS plugin that i used. it basically saved the canvas data to the photo roll. From my understanding of webos i will need to create a node.js service and write the data to a buffer and finally to the file system, there is an example for that in the forums. however what i can not figure out is how to call all of this from my phonegap app. I believe i will need to have the following in my index.html file.
<script src="/opt/PalmSDK/Current/share/framework/enyo/1.0/framework/enyo.js" type="text/javascript"></script>
and something like
enyo.create({kind: "Main"}).renderInto(document.body);
my guess i will also have to have all of the "kind" data in a js file. but how do i do the little step from my app's js file to communicate with the service that is created. I looked in the phonegap 1.0.js file and see that they are calling services this way.
this.service = navigator.service.Request('palm://com.palm.applicationManager', {
method: 'launch',
parameters: {
id: 'com.palm.app.camera',
params: {
appId: 'com.palm.app.camera',
name: 'capture',
sublaunch: true,
filename: filename
}
},
onSuccess: successCallback,
onFailure: errorCallback
});
but i also noticed it appears that it is all mojo and what i am doing is enyo, so yes i am pretty confused the moment...
seems it should be easy to call a service in webos, say here is a string of image data and write it to the file system from my existing phonegap app. and not have to do everything in enyo. anyone have a sample of a webos plugin like this or know where to point me?
thanks tim
**Update
I have created a node service now as defined below, i think that works and i am trying to make the call to the service, but it does not get to it. the test app runs on my touchpad, but when i push the button to save the image i do not get into the service. I tried to follow what was done for the camera in the phonegap0.0.1.js file this is a copy of my service, how i defined it and how i am calling it. any ideas what i am doing wrong.
services.json =
"id": "com.tim.pgmojo1.service",
"description": "FileIO Service",
"services": [
{
"name": "com.tim.pgmojo1.service",
"description": "FileIO Service",
"commands": [
{
"name": "writefile",
"assistant": "WriteFileAssistant",
"public": true
}]
}]
}
** service code
var libraries = MojoLoader.require({ name: "foundations", version: "1.0" });
var fs = IMPORTS.require("fs");
var sys = require('sys');
var WriteFileAssistant = function() {}
WriteFileAssistant.prototype.run = function(future) {
var mypath = this.controller.args.thepath;
var mydata = this.controller.args.thedata;
console.log("in write file");
console.log("path=" + thepath);
console.log("image data=" + thedata);
var data = content.replace(/^data:image\/\w+;base64,/, "");
var buf = new Buffer(data, 'base64');
fs.writeFile('/media/internal/downloads/timimage.png', buf);
}
my call to the service**
this.service = navigator.service.Request('palm://com.tim.pgmojo.service', {
method: 'writefile',
parameters: {
thepath: '/media/internal/downloads/timimage.png',
thedata: canvasData
},
onSuccess: mySuccess,
onFailure: myFailure
});
currently i have this in my index.html file since it is only for testing..
Mojo is still included on the TouchPad. You can use the same service-calling functions as PhoneGap is doing.
In Enyo, access to on-device services is handled by the enyo.PalmService kind. You can see an example of an app that has a node.js service included and how calls are made to this service at https://github.com/palm/txjs-fortunecookie

Resources