403 error when attempting to fetch google analytics 4 data from app script - google-apps-script

I am attempting to connect a custom community connector to google analytics 4 in order to get data from analytics and be able to modify it in app script and then send it to data studio. However I am having difficulty connecting and retrieving data from google analytics.
The error:
{ error:
{ code: 403,
message: 'Google Analytics Data API has not been used in project 640397821842 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/analyticsdata.googleapis.com/overview?project=640397821842 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.',
status: 'PERMISSION_DENIED',
details: [ [Object], [Object] ] } }
I have the scopes set up
"oauthScopes": [
"https://www.googleapis.com/auth/script.external_request",
"https://www.googleapis.com/auth/analytics.readonly"
],
The code i am trying to test:
function testFetch(){
const options = {
entry: { propertyId: 263290444},
"dateRanges": [{ "startDate": "2020-12-01", "endDate": "2021-03-01" }],
"dimensions": [{ "name": "country" }],
"metrics": [{ "name": "activeUsers" }],
// etc.
}
var response = UrlFetchApp.fetch(
'https://analyticsdata.googleapis.com/v1alpha:runReport', {
method: 'POST',
muteHttpExceptions: true,
headers: {
Authorization : `Bearer ${ScriptApp.getOAuthToken()}`
},
contentType: 'application/json; charset=utf-8',
payload: JSON.stringify(options)
});
var result = JSON.parse(response.getContentText());
console.log(result);

'Google Analytics Data API has not been used in project 640397821842 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/analyticsdata.googleapis.com/overview?project=640397821842 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.',
status:
The problem you are having is that you have not enabled the API in Google developer console You need to follow the link in the error message then go to library and look for Google analytics data api and enable it.
Once you have enabled it try and run your application again.

For those with the same issue who may have overlooked some steps:
Create an API project at https://console.cloud.google.com/
Make sure to connect your appscript project to your cloud API project by changing the Google Cloud Platform (GCP) Project in appscript settings (It is set to a default project when you start).
Enable the required APIs from the API Library in the cloud project.
Now you will be able to fetchurls related to the APIs you have enabled.

Related

Use appscript to track user installs of google marketplace app

We've developed a Google Marketplace app using AppsScript which we've now made live on the marketplace (https://workspace.google.com/marketplace/app/report_connector_for_salesforce_beta/977246938879). However, we're struggling to work out how to use the Google Marketplace API (https://developers.google.com/workspace/marketplace/example-calls-marketplace-api) to access the license data. Has anyone else successfully managed this?
Has anyone else managed to get this working? It would be great if there was an app for this by the way on the marketplace!
Many thanks
Andy
So far, we've created a separate Google Sheet (in the same domain as our app), and we've written a simple API call function as follows:
function getUsers() {
const options = {
muteHttpExceptions: true,
headers: {
Authorization: `Bearer ${ScriptApp.getOAuthToken()}`
}
};
let response = UrlFetchApp.fetch("https://appsmarket.googleapis.com/appsmarket/v2/licenseNotification/<our app Id>",options);
Logger.log("Refresh Response:"+response);
}
We've created a new project in the GCP, and have enabled:
Google Workspace Marketplace API
Google Workspace Marketplace SDK
We've added the following scopes to the project:
Connect to an external service https://www.googleapis.com/auth/script.external_request
View your installed application's licensing information https://www.googleapis.com/auth/appsmarketplace.license
But, when we run the code, we just keep getting the following:
Info Refresh Response:{
"error": {
"code": 403,
"message": "Not authorized to access the application ID",
"errors": [
{
"message": "Not authorized to access the application ID",
"domain": "global",
"reason": "forbidden"
}
]
}
}
This worked for me, but I needed to add "https://*.googleapis.com/" in the urlFetchWhitelist.
Is your App Id correct? Check it out at https://console.cloud.google.com/apis/api/appsmarket-component.googleapis.com/googleapps_sdk?project=*projectName*

Accessing user token in IBM Cloud Functions serverless app secured with OAuth user authentication

I am creating a serverless app using IBM Cloud Functions. My Cloud Functions API is secured with OAuth user authentication using an IBM Cloud App ID service. When a user logs into my app, an access token is generated by this service. I want to extract user data from that access token so that I can customize the user experience.
How do I access that token from within a Cloud Functions action that is coded for Node.js 10?
Example
The openwhisk webaction doc
https://github.com/apache/openwhisk/blob/master/docs/webactions.md
states that the following code
function main(params) {
return { response: params };
}
generates the following response
{
"response": {
"__ow_method": "get",
"__ow_headers": {
"accept": "*/*",
"connection": "close",
"host": "172.17.0.1",
"user-agent": "curl/7.43.0"
},
"__ow_path": ""
}
}
From that data I should be able to get HTTP request details. Specifically, I should be able to get the Authorization header value off the "__ow_headers" property of the action argument (params).
However, the same code inside an IBM Cloud Functions web action generates nothing. Nothing exists on the params object.

Trigger a cloud build pipeline using Cloud Function

I'm trying to create a cloud function listening to cloudbuilds topic and making an API call to trigger the build. I think I'm missing something in my index.js file (I'm new to Node.js). Can you provide a sample example of a Cloud Function making an API call to the Cloud Build API?
Here is my function:
const request = require('request')
const accessToken = '$(gcloud config config-helper --format='value(credential.access_token)')';
request({
url: 'https://cloudbuild.googleapis.com/v1/projects/[PROJECT_ID]/builds',
auth: {
'bearer': accessToken
},
method: 'POST',
json: {"steps": [{"name":"gcr.io/cloud-builders/gsutil", "args": ['cp','gs://adolfo-test-cloudbuilds/cloudbuild.yaml', 'gs://adolfo-test_cloudbuild/cloudbuild.yaml']}]},
},
module.exports.build = (err, res) => {
console.log(res.body);
});
I was executing the command gcloud config config-helper --format='value(credential.access_token)', copying the token, and putting it as a value to the variable accessToken. But this didn't work for me.
Here is the error: { error: { code: 403, message: 'The caller does not have permission', status: 'PERMISSION_DENIED' } }
I had the same exact problem and I have solved it by writing a small package, you can use it or read the source code.
https://github.com/MatteoGioioso/google-cloud-build-trigger
With this package you can run a pre-configured trigger from cloud build.
You can also extend to call other cloud build API endpoints.
As my understanding cloud build API requires either OAuth2 or a service account. Make sure you gave the right permission to cloud build in the gcp console under IAM. After that you should be able to download the service-account.json file.

How to determine why an Azure Function App is not triggered by a webhook

I have:
An JavaScript Azure Function in an HTTP webhook configuration; the Function provides a URL; the Function performs an action
A webhook configured in the software I hope to receive notifications from
An Azure Logic App with an HTTP/webhook step that provides a URL for the webhook notification to go to
My goal is that the Azure Function's URL receives notifications from the software's webhook and performs an action. The Azure Logic App is for testing only.
What works
When the the Azure Logic App's URL is used in the software's webhook configuration, the desired action is performed. All works as expected.
The Azure Logic App's logging shows the JSON output from the incoming webhook. I expect (but believe this may be where I am going wrong) that this is the JSON the webhook is sending to the Azure Logic App's URL. When this JSON is used in the Azure Function UI's "Test" tab > "Request body" field, the desired action is performed. All works as expected.
When the Azure Function's URL and the JSON is in a Postman request, the desired action is performed. All works as expected.
What doesn't work
When the Azure Function's URL is used in the software's webhook configuration, no action is performed. This is of course my goal. From everything I have read, I understand that this URL as a webhook endpoint should work.
Azure Function's URL
This is from Get function URL > default (Function key).
https://<app_name>.azurewebsites.net/api/content?code=<api_key>
Other Azure Function config settings
Allowed HTTP methods: GET, POST
Authorization level: Function
The JSON I believe to be coming over the webhook
{
"headers": {
"Expect": "100-continue",
"Host": "redacted",
"X-Telligent-Webhook-Sender": "redacted",
"Content-Length": "16908",
"Content-Type": "application/json; charset=utf-8"
},
"body": {
"events": [{
"TypeId": "ec9da4f4-0703-4029-b01e-7ca9c9ed6c85",
"DateOccurred": "2018-12-17T22:55:37.7846546Z",
"EventData": {
"ActorUserId": 9999,
"ContentId": "redacted",
"ContentTypeId": "redacted",
"ForumReplyId": 9999,
"ForumThreadId": 9999,
"ForumId": 9999
}
}]
}
}
I also tried with the following test code for the same results. It aligns more closely with the sample payload data provided by the software company:
What I tried
{
"events": [{
"TypeId": "ec9da4f4-0703-4029-b01e-7ca9c9ed6c85",
"DateOccurred": "2018-12-17T22:55:37.7846546Z",
"EventData": {
"ActorUserId": 9999,
"ContentId": "redacted",
"ContentTypeId": "redacted",
"ForumReplyId": 9999,
"ForumThreadId": 9999,
"ForumId": 9999
}
}]
}
Sample payload data
{
"events": [
{
"TypeId": "407ad3bc-8269-493e-ac56-9127656527df",
"DateOccurred": "2015-12-04T16:31:55.5383926Z",
"EventData": {
"ActorUserId": 2100,
"ContentId": "4c792b81-6f09-4a45-be8c-476198ba47be"
}
},
{
"TypeId": "3b75c5b9-4705-4a97-93f5-a4941dc69bc9",
"DateOccurred": "2015-12-04T16:48:03.7343926Z",
"EventData": {
"ActorUserId": 2100,
"ContentId": "4c792b81-6f09-4a45-be8c-476198ba47be"
}
}
]
}
I do not know how to determine why the Azure Function is not triggered by the webhook. The software's API documentation does not seem to provide a way to look at the JSON being sent over the webhook, although in my inexperience I may be wrong.
Is there a mechanism within Azure, or Postman, or another tool that lets me see what JSON is being sent over the webhook? Or perhaps is there another approach to determining the cause of the issue?
Thank you for any help.
This is how I got the JSON file from Azure alerts.
Install Ruby on the server
Install Sinatra with following command gem install sinatra
Create file webhook.rb and paste code bellow
require 'sinatra'
set :port, 80
set :bind, '0.0.0.0'
post '/event' do
status 204 #successful request with no body content
request.body.rewind
request_payload = JSON.parse(request.body.read)
#append the payload to a file
File.open("events.txt", "a") do |f|
f.puts(request_payload)
end
end
Run the web service with command ruby webhook.rb
JSON fill be written to file events.txt

Do you have to get Drive permission in a Google Chrome Extension in order to call the Drive API?

My Extension has the following permissions called out in the Manifest:
"oauth2": {
"client_id": "425460661917-smaehlat7c66p1ns6t90ssj3jmlrrecm.apps.googleusercontent.com",
"scopes": [
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/drive.readonly"
]
},
I only want to use Google Drive when a user explicitly grants permission. I am only interested in file metadata at this point, so when the user indicates it, I used an Ajax call to get the metadata:
$.ajax({
type: "GET",
beforeSend: function(request) {
request.setRequestHeader("Authorization", "Bearer " + token);
},
url: "https://www.googleapis.com/drive/v3/files/" + googleFileID + "?fields=sharingUser",
dataType: 'json',
processData: true,
success: function(gDocsMeta2) {// then code...
This works great.
However, every user does not want to use my app with Drive, but (I think) because of the 'drive.readonly' in the manifest, understandably, Chrome periodically pops a permission request.
Is there a way to get more situational permission? With my existing code, when the user DOES request data from Drive a permission is popped...
Any help/direction appreciated.