title: Request for reporting apiv4 for google analytics
body: <p>today i try to do a request with reporting API v4 to get data from google analytics. I write in google app script to display data in google spreadsheet.</p>
  
  <p>Here's my function:</p>
  
  <pre><code>function get_ga(){
    var now = new Date();
    var doc = SpreadsheetApp.getActiveSpreadsheet();       
    var site = doc.getSheetByName("Dashboard").getRange(2,1).getValue();
    var sheet = doc.getSheetByName("Google analytics");
    var service = getService(); 
    if (sheet==null){
      sheet = doc.insertSheet("Google analytics"); 
    }
    start_date=getstart(now);
    end_date=getend(now);
  
    if (service.hasAccess()) {
  
      var apiURL = 'https://analyticsreporting.googleapis.com/v4/reports:batchGet';
  
      var headers = {"Authorization": "Bearer " + getService().getAccessToken()};
  
      var request = {
        "reportRequests":
        [
          {
            "viewId": VIEW_ID,
            "dateRanges": [{"startDate": start_date, "endDate": end_date}],
            "metrics": [{"expression": "ga:users"}]
          }
        ]
      }
  
  
  
  
      var options = {
        "headers" : headers,
        "contentType":'application/json',
        "method" : "post",
        "payload" : JSON.stringify(request),               
        "muteHttpExceptions": true
      };
  
      try {
        var response = UrlFetchApp.fetch(apiURL, options);
      } 
      catch (e) {
        Logger.log(e);
      }
      Logger.log(response)
  
      var result = JSON.parse(response.getContentText());        
      console.log(result);
  
      if (result.error){
        return null;
      }
  
  
    }
  
    else {
      var authorizationUrl = service.getAuthorizationUrl();
      Logger.log('Open the following URL and re-run the script: %s', authorizationUrl);
      return 0;
  
    }
  
  }
  </code></pre>
  
  <p>Of course i have a OAuth2.0.gs file with:</p>
  
  <pre><code>function getService() {
    // Create a new service with the given name. The name will be used when
    // persisting the authorized token, so ensure it is unique within the
    // scope of the property store.
    return OAuth2.createService('searchconsole')
  
        // Set the endpoint URLs, which are the same for all Google services.
        .setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
        .setTokenUrl('https://accounts.google.com/o/oauth2/token')
  
  
        // Set the client ID and secret, from the Google Developers Console.
        .setClientId(CLIENT_ID)
        .setClientSecret(CLIENT_SECRET)
  
        // Set the name of the callback function in the script referenced
        // above that should be invoked to complete the OAuth flow.
        .setCallbackFunction('authCallback')
  
        // Set the property store where authorized tokens should be persisted.
        .setPropertyStore(PropertiesService.getUserProperties())
  
        // Set the scopes to request (space-separated for Google services).
        // this is Search Console read only scope for write access is:
        // https://www.googleapis.com/auth/webmasters
        .setScope('https://www.googleapis.com/auth/webmasters')
  
        // Below are Google-specific OAuth2 parameters.
  
        // Sets the login hint, which will prevent the account chooser screen
        // from being shown to users logged in with multiple accounts.
        .setParam('login_hint', Session.getActiveUser().getEmail())
  
        // Requests offline access.
        .setParam('access_type', 'offline')
  
        // Forces the approval prompt every time. This is useful for testing,
        // but not desirable in a production application.
        .setParam('approval_prompt', 'force');
  }
  
  
  function authCallback(request) {
    var searchConsoleService = getService();
    var isAuthorized = searchConsoleService.handleCallback(request);
    if (isAuthorized) {
      return HtmlService.createHtmlOutput('Success! You can close this tab.');
    } else {
      return HtmlService.createHtmlOutput('Denied. You can close this tab');
    }
  }
  </code></pre>
  
  <p>Finally i have a variables.gs file with my differents ID and my VIEW id from google analytics, corresponding to the website i want data from. Something important is that i see data in google analytics but i'm not the owner of the website ;</p>
  
  <pre><code>    //GSC
  var CLIENT_ID = '*******************************************';
  var CLIENT_SECRET = '*****************';
  
  //GA
  var CLIENT_ID2 = '************************************';
  var CLIENT_SECRET2 = '**************';
  var VIEW_ID = '********';
  </code></pre>
  
  <p>with google search console and google analytics API enabled.
  All my functions are perfectly working with google search console.</p>
  
  <p>The error is:{"error":{"status":"PERMISSION_DENIED","code":403,"message":"Request had insufficient authentication scopes."}}
  The first thing strange i noticed is that i use client ID and client secret from Google Search console for authentification for google analytics (see my OAuth2.0.gs file) but it seems to work; otherwise i 'll get a 401 error.</p>