title: Google Analytics API V3 / OAuth 2
body: <p>I've desperately tried to figure this out on my own, and did not want to come to SO with this question, but I'm at my wits end (no thanks to the api / oauth docs).</p>
  
  <p>I'm working in PHP and I'm trying to avoid using the <code>Google_Client</code> and <code>AnalyticsService</code> classes, by using REST on the <code>analytics.data.ga.get</code> method.</p>
  
  <p><code>STEP #1: Create an API Project for a Web Application</code></p>
  
  <p>I go to the <a href="https://code.google.com/apis/console/" rel="noreferrer">api console</a> and create a project with analytics services and get an OAuth Client ID and Secret. </p>
  
  <p>I'm under the impression that I can create a Client ID for an <a href="https://developers.google.com/accounts/docs/OAuth2#installed" rel="noreferrer">Installed Application</a> or a <a href="https://developers.google.com/accounts/docs/OAuth2#webserver" rel="noreferrer">Web Application</a> because I'm doing the initial token handshaking manually.  Please correct me if I'm wrong.</p>
  
  <p>I create a Client ID for web applications and get my Client ID <code>xxxxxxxxxxxxxx.apps.googleusercontent.com</code>, Client secret <code>yyyyyyyyyyyyyyy</code>, and my Redirect URI is <code>http://localhost:9002</code></p>
  
  <p><code>STEP #2: Request initial API access</code></p>
  
  <p>I enter this link; <code>https://accounts.google.com/o/oauth2/auth?response_type=code&amp;client_id=xxxxxxxxxxxxxx.apps.googleusercontent.com&amp;redirect_uri=http://localhost:9002&amp;scope=https://www.googleapis.com/auth/analytics.readonly&amp;access_type=offline</code></p>
  
  <p>The <code>access_type=offline</code> is because I'm using REST, and do not expect "the user" (myself) to manually deal with redirects / popups every time I need a refreshed token.</p>
  
  <p>The above request returns <code>http://localhost:9002?code=4/KModH0K_xxxxxxxxxxxxxxxxxxx9Iw.gikOaYRDWywTshQV0ieZDArCOX8XdwI</code></p>
  
  <p>Code <code>4/KModH0K_xxxxxxxxxxxxxxxxxxx9Iw.gikOaYRDWywTshQV0ieZDArCOX8XdwI</code> is my permission to request the API Token.</p>
  
  <p><code>STEP #3: Request First Token</code></p>
  
  <p>Because of my company’s IT issues, I’m forced to use PHP 5.2.17 and I do not have access to PHP cURL, so I’m using <code>file_get_contents</code> and <code>stream_context_create</code>.</p>
  
  <p>The first token is requested with a PHP <code>file_get_contents()</code>;</p>
  
  <pre><code>$opts = array(
      'http' =&gt; array(
          'method' =&gt; 'POST',
          'header' =&gt; 'Content-Type: application/x-www-form-urlencoded',
          'content' =&gt; 'code=4/KModH0K_xxxxxxxxxxxxxxxxxxx9Iw.gikOaYRDWywTshQV0ieZDArCOX8XdwI&amp;client_id=xxxxxxxxxxxxxx.apps.googleusercontent.com&amp;client_secret=yyyyyyyyyyyyyyy&amp;redirect_uri=http://localhost:9002&amp;grant_type=authorization_code'
      )
  );
  
  $context = stream_context_create($opts);
  
  $result = file_get_contents('https://accounts.google.com/o/oauth2/token', false, $context);
  var_dump($result);
  </code></pre>
  
  <p>The content parameters must be in a single line.</p>
  
  <p>The above code returns my <code>access_token</code> and <code>refresh_token</code> in json format</p>
  
  <p><code>string(195) "{ "access_token" : "ya29.AHES6wwwwwwwwwwwwwwwVEBXE6XRbC-Q-pP0wZWdoIm9H804ro", "token_type" : "Bearer", "expires_in" : 3600, "refresh_token" : "1/8tXvdUKcSEcaaxVqqqqqqqqqqqqqoYpj2KSS9qwWI" }"</code></p>
  
  <p>The refresh token I must store in a safe place, like a DB or protected txt file, which is called upon when my access_token has timed out.</p>
  
  <p><code>STEP #4: Request Analytics Data</code></p>
  
  <p>Now from what I understand, I’m ready to roll and should be able to use my <code>access_token</code> to make requests to <code>https://www.googleapis.com/analytics/v3/data/ga</code>.</p>
  
  <p>I do this by sending this request;</p>
  
  <pre><code>$request = 'https://www.googleapis.com/analytics/v3/data/ga' .
      '?ids=ga%3Aaaaaaaaa' .
      '&amp;start-date=2012-12-07' .
      '&amp;end-date=2012-12-09' .
      '&amp;metrics=ga%3Avisits';
  
  $opts = array(
      'http' =&gt; array(
          'method' =&gt; 'GET',
          'header' =&gt; 'Content-Type: application/x-www-form-urlencoded\r\n' .
                      'Authorization: Bearer ya29.AHES6wwwwwwwwwwwwwwwVEBXE6XRbC-Q-pP0wZWdoIm9H804ro \r\n'
          )
  );
  
  $context = stream_context_create($opts);
  
  $result = file_get_contents($request, FALSE, $context);
  var_dump($result);
  </code></pre>
  
  <p>This request returns a <code>401 Unauthorized</code> error.  I take this as meaning my request is properly formed and making the connection to <code>https://www.googleapis.com/analytics/v3/data/ga</code>.</p>
  
  <p>Also, according to this doc <a href="https://developers.google.com/analytics/devguides/reporting/core/v3/reference#quota" rel="noreferrer">Getting Full Quota</a>, I can make the request with the <code>access_token</code> in the URL like this;</p>
  
  <pre><code>$request = 'https://www.googleapis.com/analytics/v3/data/ga' .
      '?ids=ga%3A48564799' .
      '&amp;access_token=ya29.AHES6wwwwwwwwwwwwwwwVEBXE6XRbC-Q-pP0wZWdoIm9H804ro' .
      '&amp;start-date=2012-12-07' .
      '&amp;end-date=2012-12-09' .
      '&amp;metrics=ga%3Avisits';
  
  $result = file_get_contents($request, FALSE);
  
  $result = json_decode($result);
  
  var_dump($result);
  </code></pre>
  
  <p>This time I receive <code>403 error</code>, in which google includes the response <code>User does not have sufficient permissions for this profile</code>. </p>
  
  <p><code>QUESTION #1</code></p>
  
  <p>Am I’m missing something in the API console or a process in the token acquisition?  I’m assuming I’m not, because I’m ultimately acquiring the <code>access_token=ya29</code> and refresh token.</p>
  
  <p><code>QUESTION #2</code>
  Maybe I’m completely off basis in assuming I can do this with simple https reqests?  Do I have to use the <code>Google_Client</code> and <code>AnalyticsService</code> classes?  I don’t think this is the case, but maybe I’m wrong.</p>
  
  <p><code>QUESTION #3</code>
  Do I need to use a ‘key’ in my request?
  <code>&amp;key=bbbbbbbbbbbbbbbb</code></p>
  
  <p><code>QUESTION #4</code></p>
  
  <p>By using PHP 5.2.17 am I missing something? (besides 5.3 or 5.4 themselves)</p>
  
  <p>For example, in some versions of PHP, in <code>stream_context_create</code>, the header should be in an array and not a string, like this;</p>
  
  <pre><code>$opts = array(
      'http' =&gt; array(
          'method' =&gt; 'GET',
          'header' =&gt; array(
              'Content-Type: application/x-www-form-urlencoded',
              'Authorization: Bearer ya29.AHES6wwwwwwwwwwwwwwwVEBXE6XRbC-Q-pP0wZWdoIm9H804ro '
          )
      )
  );
  </code></pre>
  
  <p>But I don’t think that it’s an issue in my case.  I’m just curious if these HTTP request need to be formed a different way (without using curl).</p>
  
  Any insights and thoughts would be greatly appreciated