Google Analytics API V4 does not work with GA4 account - google-api

Is it possible to get data from new Google Analytics (GA4) accounts through API V4? It always returns the following error message:
{ "error": { "code": 403, "message": "User does not have sufficient permissions for this profile.", "errors": [ { "message": "User does not have sufficient permissions for this profile.", "domain": "global", "reason": "forbidden" } ], "status": "PERMISSION_DENIED" } }
I can do it perfectly on UA accounts.
Is there any API (web server request - OAuth) specific to this new account type?
property id
Here is the code used (PHP):
require_once __DIR__ . '/vendor/autoload.php';
session_start();
$client = new Google_Client();
$client->setAuthConfig(__DIR__ . '/FILE.json');
$client->addScope(Google_Service_Analytics::ANALYTICS_READONLY);
$client->setAccessToken($_SESSION['access_token']);
$analytics = new Google_Service_AnalyticsReporting($client);
$response = getReport($analytics);
printResults($response);
function getReport($analytics){
$dateRange = new Google_Service_AnalyticsReporting_DateRange();
$dateRange->setStartDate("7daysAgo");
$dateRange->setEndDate("today");
$sessions = new Google_Service_AnalyticsReporting_Metric();
$sessions->setExpression("name");
$sessions->setAlias("sessions");
$request = new Google_Service_AnalyticsReporting_ReportRequest();
$request->setViewId('307566943');
$request->setDateRanges($dateRange);
$request->setMetrics(array($sessions));
$body = new Google_Service_AnalyticsReporting_GetReportsRequest();
$body->setReportRequests( array( $request) );
return $analytics->reports->batchGet( $body );
}

User does not have sufficient permissions for this profile
Means that the user you have authenticated your application with. Does not have permission to access the Google analytics view you are trying to extract data from.
The issue can also be caused if you are trying to use the Google analytics reporting api with a Google analytics GA4 account. As GA4 property id are not the same as UA view ids. The system gets confused and assumes you just dont access.
The solution is to authenticate the app with a user that has access to that view or grant the user access. And to check that you are using the correct api for the type of google analytics you are trying to access.
UA vs GA4
Also remember that to extract date from a GA4 account you need to use the Google analytics data api. If you have extracted data from UA accounts you have been using the Google analytics reporting api. These are two completely diffrent APIs with diffrent methods.
Google analytics data api quick start
require 'vendor/autoload.php';
use Google\Analytics\Data\V1beta\BetaAnalyticsDataClient;
use Google\Analytics\Data\V1beta\DateRange;
use Google\Analytics\Data\V1beta\Dimension;
use Google\Analytics\Data\V1beta\Metric;
/**
* TODO(developer): Replace this variable with your Google Analytics 4
* property ID before running the sample.
*/
$property_id = 'YOUR-GA4-PROPERTY-ID';
// Using a default constructor instructs the client to use the credentials
// specified in GOOGLE_APPLICATION_CREDENTIALS environment variable.
$client = new BetaAnalyticsDataClient();
// Make an API call.
$response = $client->runReport([
'property' => 'properties/' . $property_id,
'dateRanges' => [
new DateRange([
'start_date' => '2020-03-31',
'end_date' => 'today',
]),
],
'dimensions' => [new Dimension(
[
'name' => 'city',
]
),
],
'metrics' => [new Metric(
[
'name' => 'activeUsers',
]
)
]
]);
// Print results of an API call.
print 'Report result: ' . PHP_EOL;
foreach ($response->getRows() as $row) {
print $row->getDimensionValues()[0]->getValue()
. ' ' . $row->getMetricValues()[0]->getValue() . PHP_EOL;
}

Related

Google API not always returning profile data

Using django-allauth, I am allowing users to log in through their Google profiles using the all of the following settings:
SOCIALACCOUNT_PROVIDERS = {
'google': {
'SCOPE': [
'profile',
'email',
'https://www.googleapis.com/auth/gmail.labels',
'https://www.googleapis.com/auth/gmail.modify'
],
'AUTH_PARAMS': {
'access_type': 'offline',
}
}
}
SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE = [
'profile',
'email',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
]
SOCIALACCOUNT_QUERY_EMAIL = True
SOCIALACCOUNT_EMAIL_VERIFICATION = "none"
SOCIALACCOUNT_EMAIL_REQUIRED = False
SOCIALACCOUNT_STORE_TOKENS = True
SOCIALACCOUNT_AUTO_SIGNUP = True
For some reason, the extra data I am receiving is inconsistent. Sometimes, I receive all of the profile data. Sometimes, I don't get the user's name. Sometimes I don't even get the user's email. The only thing I seem to consistently get is an id and a link to a avatar photo.
The accounts I am testing are all my own and I am able to verify that they all have their publicly available names saved correctly. Google seems to only sometimes return the full set of permissible data from the profile scope. I should note that the data it returns is consistent per each account. I never get different data for an account. Has anyone had an experience like this?

View attachments added through API docusign

I'm using the following endpoint to add an attachment to an envelope:
PUT /v2.1/accounts/{accountId}/envelopes/{envelopeId}/attachments
Apparently the request goes well because I get this return:
"attachments" => array:2 [
0 => array:4 [
"attachmentId" => "656A658D-AD83-438C-B58D-86738486349C"
"attachmentType" => "png"
"name" => "asdas"
"accessControl" => "SenderAndAllRecipients"
]
]
But nothing appears to the signers on the view. Where the signers can download or visualize the attachments that were added through the api?
UPDATE
The method to send the attachments:
public function addAttachments($saleContract, $envelopeId)
{
$attachments = array();
foreach ($saleContract->document as $document){
array_push($attachments, [
'accessControl' => 'senderAndAllRecipients',
'attachmentId' => $document->id,
'attachmentType' => \File::extension($document->storage_file_name),
'data' => base64_encode(Storage::disk('sienge')->get($document->storage_file_name)),
'name' => $document->file_name,
]);
}
Docusign::addEnvelopeAttachments($envelopeId, $attachments);
}
These are Envelope API Attachments and can be access only via API. When you add these attachments via API, then you can access via API only and will not be available on the Signing screen.
These are like metadata available in an envelope which should not be shown on the Signing screen, and can be accessed via API only. Dev Doc explains how to read these API attachments

Can't impersonate on a service-to-service oauth request to google calendar api in ruby

Hi I was late night hacking and testing google api client for Ruby.
I fell in an error perhaps by missunderstanding.
What I already done
I already created an app in google developer console
I enabled the calendar api
I created the Server Key and downloaded the p12.
I managed to see that calendar metadata using the google api explorer and browser oauth, so the ids are confirmed and the permissions too as browser's oauth can view the metadata
What I'm triying to do:
I'm triying to get metadata (I will try events later) from a privately shared calendar where I have read permissions (trough a group) in a google apps for work account in Ruby on a service to service auth
How I'm triying to do it
With this code:
require 'google/api_client'
require 'pp'
client = Google::APIClient.new
cal = client.discovered_api('calendar','v3')
id = 'xxxxxxxxxxxxxxxxxxxxxx#group.calendar.google.com' # id is the confirmed calendar ID
key = Google::APIClient::KeyUtils.load_from_pkcs12('sl.p12', 'notasecret')
client.authorization = Signet::OAuth2::Client.new(
:token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
:audience => 'https://accounts.google.com/o/oauth2/token',
:scope => 'https://www.googleapis.com/auth/calendar',
:issuer => 'xxxxxxxxxxxxxxxxxxxxxxxxxxx#developer.gserviceaccount.com', # confirmed issuer
:signing_key => key
)
client.authorization.fetch_access_token!
result = client.execute(
:api_method => cal.calendars.get,
:parameters => { 'calendarId' => id }
)
puts result.response.body
pp result
Results colected
When I do this y get a 404, something like "that calendar does not exists"
{
"error": {
"errors": [
{
"domain": "global",
"reason": "notFound",
"message": "Not Found"
}
],
"code": 404,
"message": "Not Found"
}
}
But if i change id per 'primary'
I get:
{
"kind": "calendar#calendar",
"etag": "\"dAAhx6wYoPw2vqRAe54lk5wa0XQ/WEglF6_c5pVHKyggcENvvX1cS9g\"",
"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx#developer.gserviceaccount.com", #same as issuer id ??? WTF
"summary": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx#developer.gserviceaccount.com",
"timeZone": "UTC"
}
Which seems to be a calendar but it's like the default calendar for the "email issuer" account that appears in the server key "email" field
I also tried to ad a :person = 'email' field to client.authorization but then I get an error creating the auth token
I couldn't find a way to access the api as other mail account dirrerent from that #developer.gserviceaccount.com, so what I'm doing wrong?
You can either share the calendar with the service account's email or follow these steps to allow the service account to impersonate any user on that domain, in which case you have to pass the :person => 'email' parameter.

How to execute a query on tin-can statements?

I am using Learning Locker (Learning Record Store).
I succeed inserting statements to it via the REST API.
But I did not succeed fetching statements from it.
How do I preform a query on statements? REST API?
I used tinCanPhp library. This is how you establish a connection with the Learning Locker database and query it in PHP. For example:
$lrs = new TinCan\RemoteLRS(
'endpoint/public/data/xAPI/',
'1.0.1',
'username',
'key'
);
$actor = new TinCan\Agent(
[ 'mbox' => 'mailto:dikla#gmail.com' ]
);
$verb = new TinCan\Verb(
[ 'id' => 'http://adlnet.gov/expapi/verbs/progressed' ]
);
$activity = new TinCan\Activity(
[ 'id' => 'http://game.t-shirt' ]
);
$statement = new TinCan\Statement(
[
'actor' => $actor,
'verb' => $verb,
'object' => $activity,
]
);
//get All Actor activity by his unique id
function getAllActorActivity($actorUri){
global $lrs;
$actor = new TinCan\Agent(
[ 'mbox' => $actorUri ]//actorUri should look like this 'mailto:dikla#gmail.com'
);
$answer=$lrs->queryStatements(['agent' => $actor]);
return $answer;
}
If it's via javascript you can use the ADL xAPI Wrapper. It simplifies communication with an LRS... https://github.com/adlnet/xAPIWrapper#get-statements
In general you do a GET request on endpoint /statements... try just that first and see if you get a json response with a "statements" and a "more" property. Then if that works, you can narrow down results with filters. See the spec for the details and options. https://github.com/adlnet/xAPI-Spec/blob/master/xAPI.md#stmtapiget
try that curl command.. it should return a statement result albeit from the ADL LRS...
curl --user tom:1234 GET https://lrs.adlnet.gov/xapi/statements

The merge tags in mandrill don't work in codeigniter

I use Mandrill plugin for Codeigniter.
I created HTML template through Mandrill account, named fess1 with merge tag FNAME, after I published it.
Example:
...
<p>
<span>Hi *|FNAME|*,<br></span>
</p>
....
Now I try to send mail from codeigniter like:
private function sendMailMandrill($owner_name,$business_name,$owner_email){
$message = array('dest_mail' => $owner_email);
$message['to'] = array(array('email' => 'mim#wefi.com'));
$mergeVars[] = array(
'rcpt' => array(array('email' => 'mim#wefi.com')),
'vars' => array(
array(
'name' => 'FNAME',
'content' => 'Fessy'
)
)
);
$message['merge'] = true;
$template_name = 'fess1';
$template_content = array( // I don't know what I need to provide here, left it empty
array(
'name' => 'example name',
'content' => 'example content'
)
);
$message['merge_vars'] = $mergeVars;
return $this->mandrill->messages_send_template($template_name, $template_content, $message);
}
The result:
I get the mail, based on fess1 template, but with the tag *|FNAME|*.
Sounds like Mandrill didn't recognize the merge tag.
I used mandrill->messages_send_template but since my template stored into Mandrill account I have no clue what I need to provide for $template_content.
So I wrote dummy info there.
Did I miss something?
Thank you,
[EDIT]
From logs this is what I send:
{
"template_name": "fess1",
"template_content": [
{
"name": "example name",
"content": "example content"
}
],
"message": {
"owner_name": "עידו",
"business_name": "פלאפל מוסקו",
"dest_mail": "maxim#wifi.com",
"to": [
{
"email": "maxim#wifi.com"
}
],
"merge": "true",
"merge_vars": [
{
"rcpt": [
{
"email": "maxim#wifi.com"
}
],
"vars": [
{
"name": "FNAME",
"content": "Fessy"
}
]
}
]
},
"key": "xxxxxxxxxxxxxxxx"
}
You can provide blank information for the template_content parameter. That parameter allows you to use mc:edit regions in your template. It is a required parameter, but a blank array will suffice if all of the content is in your template in Mandrill.
As for whether the merge_vars were recognized, the first thing we recommend is inspecting the API Logs for your account (Settings > API Logs) since that will show you the JSON that Mandrill received. You can then compare that to the expected JSON format from the Mandrill API docs: https://mandrillapp.com/api/docs/messages.JSON.html#method=send-template
It looks like your arrays may not be nested as expected. Once you view the JSON that's being generated as compared with the expected format, you can also view the PHP documentation for the Mandrill PHP client. It may not be identical to the CodeIgniter plugin, but should give you an idea of how the merge_vars parameter would be structured in PHP: https://mandrillapp.com/api/docs/messages.php.html
In mergeVars you created array instead key:value. Change it to:
'rcpt' => 'mim#wefi.com',

Resources