Google Analytics Reporting API - Get Activity data via Client ID - google-analytics-api

I am trying to get user activity data via his client id using Google Analytics api. Take a look at the below image:
Now highlighted text is users client id, it could be user id too, and when I trying to get it via Google's playground, I get the correct response and activity data which is required, like:
and this is the response:
which is required and OK.
but I want this data via API, and have searched the web to get it, but nothing helped me.
Here is sample code Google showing i.e.
function getReport($analytics) {
// Replace with your view ID, for example XXXX.
$VIEW_ID = "<REPLACE_WITH_VIEW_ID>";
// Create the DateRange object.
$dateRange = new Google_Service_AnalyticsReporting_DateRange();
$dateRange->setStartDate("7daysAgo");
$dateRange->setEndDate("today");
// Create the Metrics object.
$sessions = new Google_Service_AnalyticsReporting_Metric();
$sessions->setExpression("ga:sessions");
$sessions->setAlias("sessions");
// Create the ReportRequest object.
$request = new Google_Service_AnalyticsReporting_ReportRequest();
$request->setViewId($VIEW_ID);
$request->setDateRanges($dateRange);
$request->setMetrics(array($sessions));
$body = new Google_Service_AnalyticsReporting_GetReportsRequest();
$body->setReportRequests( array( $request) );
return $analytics->reports->batchGet( $body );
}
I do found a class for adding user to request i.e.
$user = new Google_Service_AnalyticsReporting_User();
$user->setType("CLIENT_ID");
$user->setUserId("660467279.1539972080");
but this class Google_Service_AnalyticsReporting_ReportRequest which accepts conditions/filters for query does not have such method to accept user object.
How can I achieve this?

You should use this function: $analytics->userActivity->search().
$search = new Google_Service_AnalyticsReporting_SearchUserActivityRequest();
$search->setViewId($VIEW_ID); // Google Analytics View ID
$dateRange = new Google_Service_AnalyticsReporting_DateRange();
$dateRange->setStartDate("7daysAgo");
$dateRange->setEndDate("today");
$search->setDateRange($dateRange);
$user = new Google_Service_AnalyticsReporting_User();
$user->setType("USER_ID"); // or CLIENT_ID if you are not using custom USER ID views
$user->setUserId($user_id); // The actual user's ID as stored in your DB passed to GA
$search->setPageSize(10); // Number of results you want to pull
$search->setUser($user);
return $analytics->userActivity->search($search); // Perform the search query.
Alternatively you can also pass the params to search() like:
$params = [
'metrics' => //Your comma separated desired metrics
'dimmensions' => //Your comma separated custom dimmentions
]
return $analytics->userActivity->search($search, $params);

Related

Dingo Api response->created | location and content example

I am creating API with Laravel 5.2 and Dingo API package. When a user is created, I want to return 201 response with the new $user->id.
My Code
return $this->response->created();
As per Dingo documentatio, I can provide a location and $content as parameters in the created() function.
My question is, what location information I need to return here and I tried to set my new user as $content, but it's not working or I am not sure what to expect.
Can someone please explain this created() function?
What this does is set the Location header, as seen in the source:
/**
* Respond with a created response and associate a location if provided.
*
* #param null|string $location
*
* #return \Dingo\Api\Http\Response
*/
public function created($location = null, $content = null)
{
$response = new Response($content);
$response->setStatusCode(201);
if (! is_null($location)) {
$response->header('Location', $location);
}
return $response;
}
So, in your example since you're creating a new user, you might send the users profile page as the location, something like:
return $this->response->created('/users/123');
As for the content, as you can see in the function this sets the content on the return. In your case, it would probably be a json string with the new user information, something like:
return $this->response->created('/users/123', $user); // laravel should automatically json_encode the user object

In a REST API, to GET a resource, should I include the resource ID in the url?

I am trying to create an REST API for creating and retrieving files in my database. The tutorial I was following uses the following method to retrive a single file:
$app->get('/file/:file_id', 'authenticate', function($file_id) {
global $user_id;
$response = array();
$db = new DbHandler();
// fetch file
$result = $db->getFile($file_id, $user_id);
if ($result != NULL) {
$response["error"] = false;
$response["id"] = $result["id"];
$response["file"] = $result["fileLocation"];
$response["status"] = $result["status"];
$response["createdAt"] = $result["created_at"];
echoRespnse(200, $response);
} else {
$response["error"] = true;
$response["message"] = "The requested resource doesn't exist";
echoRespnse(404, $response);
}
});
Here they are using the HTTP GET method and are specifying the file ID in the URL, is it OK to do this, safety wise? Would it not be safer to use POST and hide the file ID in the body of the request, or should they not be putting the file ID in a header with the GET request? or is it not something I should be worried about?
In REST post method is used to create a new resource not to get it. Get method is used for fetching the resource and you need to specify the ID to determine particular resource. Passing it via URL is a common practice. You can randomly generate such ID to make it harder to guess.
As Opal said above, the ID is used to identify a resource. If you are unsure have a read of this - http://blog.teamtreehouse.com/the-definitive-guide-to-get-vs-post

Modify SingleResult<T> from TableController in Azure Mobile Services before returning it to the client?

I am using Azure Mobile Services. I have a TableController<Photo>. In the controller, I can retrieve a single photo by id successfully. No problems using the following method:
//works
public SingleResult<Photo> GetPhoto(string id)
{
return Lookup(id);
}
However, since the photo is stored in Azure storage as a private blob, I want to tack on the SAS (Shared access signature) to allow my mobile client direct read access to the Azure blob for a given period of time.
In the GetPhoto call, I am successfully retrieving the SAS using the CloudBlobClient (removed for brevity).
I have defined a property on Photo called SasQueryString. I want to set it on the <Photo> object retrieved using Lookup(id) but the data returned from Lookup(id) is an IQueryable, not my strongly typed Photo object.
//! INCORRECT ! -- because photoResult is IQueryable
public SingleResult<Photo> GetPhoto(string id)
{
SingleResult<Photo> photoResult = Lookup(id);
//SingleResult<Photo> does not contain SasQueryString
photoResult.SasQueryString = "SAS from CloudBlobClient";
return photoResult;
}
If I do this, I can set the SasQueryString:
Photo photoResult = (Photo)Lookup(id).Queryable.FirstOrDefault<Photo>();
photoResult.SasQueryString = "SAS from CloudBlobClient";
However, I'm not sure how to return this strongly typed object as a SingleResult<Photo>.
//! INCORRECT ! -- this doesn't work because the Create method expects an IQueryable
return SingleResult<Photo>.Create(photoResult);
I've also tried this but photoResult is anIQueryable so I can't set the strongly typed SasQueryString value this way either.
//! INCORRECT !
var photoResult = Lookup(id).Queryable.Select(x => new Photo()
{
Id = x.Id,
TheOtherFields = x.TheOtherFields
});
photoResult.SasQueryString = "SAS from CloudBlobClient";
I am obviously missing something crucial here but it seems like I should be able to combine the lookup for the photo and the request for the SAS into a single call that returns my photo data after tacking on the SAS ticket...
== UPDATE ==
I found the following example: Creating a Leaderboard App with Azure Mobile Services .NET Backend. It is doing something similar to what I want to do but I have yet to try it.
// GET tables/PlayerRank/48D68C86-6EA6-4C25-AA33-223FC9A27959
public SingleResult<PlayerRankDto> GetPlayerRank(string id)
{
var result = Lookup(id).Queryable.Select(x => new PlayerRankDto()
{
Id = x.Id,
PlayerName = x.Player.Name,
Score = x.Score,
Rank = x.Rank
});
return SingleResult<PlayerRankDto>.Create(result);
}
which modified for my situation might look like the following:
public SingleResult<Photo> GetPhoto(string id)
{
var result = Lookup(id).Queryable.Select(x => new Photo()
{
Id = x.Id,
ImageUri = x.ImageUri,
SasQueryString = GetSas(id),
});
return SingleResult<PlayerRankDto>.Create(result);
}
You are not doing it the right way:
When you get the a list of Photos or a Photo it will give the data from storage in database and SasQueryString is not storaged, only the Url from blob storage should be;
You only provide SasQueryString in Insert or Update methods, because you need to define the url or update the url if need;
Note: Get methods do not change data
When a client app insert a photo the backend should do:
create the url for the photo and generate the SasQueryString
save the photo, with the url create, in database
before return the photo set the SasQueryString
client app upload the image to blob using the SasQueryString and url you provided
Why you have a Photo and a Controller for Photo???
If you have an object "Car" that has an image, it should have "car.Url" and a class similar to BlobItem.cs and you can see BlobStorageExtensions.cs.
Note: BlobItem.cs will be a not mapped property, I do not want save it on database.
I need to create a sample with it and the nugets...

AngularJS $resource creating new object instead of updating object

// Set up the $resource
$scope.Users = $resource("http://localhost/users/:id");
// Retrieve the user who has id=1
$scope.user = $scope.Users.get({ id : 1 }); // returns existing user
// Results
{"created_at":"2013-03-03T06:32:30Z","id":1,"name":"testing","updated_at":"2013-03-03T06:32:30Z"}
// Change this user's name
$scope.user.name = "New name";
// Attempt to save the change
$scope.user.$save();
// Results calls POST /users and not PUT /users/1
{"created_at":"2013-03-03T23:25:03Z","id":2,"name":"New name","updated_at":"2013-03-03T23:25:03Z"}
I would expect that this would result in a PUT to /users/1 with the changed attribute. But it's instead POST to /users and it creates a new user (with a new id along with the new name).
Is there something that I'm doing wrong?
AngularJS v1.0.5
you just need to tell the $resource, how he has to bind the route-parameter ":id" with the JSON Object:
$scope.Users = $resource("http://localhost/users/:id",{id:'#id'});
This should work,
regards
thanks for the answer. It worked in the end for me too.
As a side note, I was using .NET WEB API and my entity has an Id property (UPPER CASE "I").
The PUT and DELETE worked only after I used the following:
$scope.Users = $resource("http://localhost/users/:Id",{Id:'#Id'});
Hope it helps.

Doctrine Mongo ODM merge for externally modified data

I'm writing a Symfony2 app that allows mobile users to create and update "Homes" via a REST service. I'm using MongoDB as the storage layer and Doctrine MongoDB ODM to do the Document handling.
The GET /homes/{key} and POST /homes methods are working fine. The problem comes when I attempt to update an existing Home with PUT /homes/{key}.
Here's the current code:
/**
* PUT /homes/{key}
*
* Updates an existing Home.
*
* #param Request $request
* #param string $key
* #return Response
* #throws HttpException
*/
public function putHomeAction(Request $request, $key)
{
// check that the home exists
$home = $this->getRepository()->findOneBy(array('key' => (int) $key));
// disallow create via PUT as we want to generate key ourselves
if (!$home) {
throw new HttpException(403, 'Home key: '.$key." doesn't exist, to create use POST /homes");
}
// create object graph from JSON string
$updatedHome = $this->get('serializer')->deserialize(
$request->getContent(), 'Acme\ApiBundle\Document\Home', 'json'
);
// replace existing Home with new data
$dm = $this->get('doctrine.odm.mongodb.document_manager');
$home = $dm->merge($updatedHome);
$dm->flush();
$view = View::create()
->setStatusCode(200)
->setData($home);
$response = $this->get('fos_rest.view_handler')->handle($view);
$response->setETag(md5($response->getContent()));
$response->setLastModified($home->getUpdated());
return $response;
}
The JSON string passed to the action is successfully deserialized to my Document object graph by JMSSerializer, but when I attempt the merge & flush, I get the error:
Notice: Undefined index: in ..../vendor/doctrine/mongodb-odm/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataInfo.php line 1265
I've been attempting to follow the documentation here: http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/reference/working-with-objects.html#merging-documents
Is there something I need to do to the deserialized Home before attempting to merge it? Is merge the wrong method?
Thanks.
The only way I found to do this is to create a method in your document class that takes the updated document (e.g. $updatedHome) as a parameter and then just copies the required fields over into the existing document (e.g. $home).
So above, the code:
// replace existing Home with new data
$dm = $this->get('doctrine.odm.mongodb.document_manager');
$home = $dm->merge($updatedHome);
$dm->flush();
can be replaced with:
// replace existing Home with new data
$home->copyFromSibling($updatedHome);
$this->getDocumentManager()->flush();
and then it will work.