function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
OldDeadBugOldDeadBug 

Google Analytics Callout via Batch APEX requires two callouts, but only one goes through

I'm probably doing this wrong, but I've set up a process to get a set of Campaign reports from Google Analytics which is failing.

 

The problem appears o be that I nee twodifferent callouts: one for the authenitication, another for the actual query once I've received the authentication token.

 

I'm not an expert on callouts but is ther some way to combine the authentication with the query??

 

Here's what I have:

 

Authenntication:

Http m_http = new Http();
HttpRequest req = new HttpRequest();

String content = 'accountType=GOOGLE&Email='+username+'&Passwd='+passwd+'&service='+service;

req.setEndpoint('https://www.google.com/accounts/ClientLogin');
req.setHeader('Content-Type','application/x-www-form-urlencoded');
req.setHeader('User-Agent','salesforce-toolkit-googledata/21');
req.setMethod('POST');
req.setBody(content);

httpResponse response = m_http.send(req);

 The response returns the clientLoginToken, which I thought would allow me to then callout to GA to get the report data I want:

 

 

HttpRequest req = new HttpRequest();
HttpResponse response = new HttpResponse();

req.setEndpoint(URL);
req.setMethod('GET');
req.setHeader('content-type', CONTENT_TYPE_URL );
req.setHeader('Authorization','GoogleLogin auth='+clientLoginToken);
req.setHeader('Accept-Encoding','compress, gzip');

Http http = new Http();
response = http.send(req);

 

 

As far as I know, and I have to believe I have it wrong, this is the process for getting ay data out of Google Analytics, unless there is some way to combine the login request with the query in the same callout, which I don't know how to do if it is possible.

 

This is being used to update Campaigns in SFDC, for which there may be quite a few and for which a Batch Process needs to be employed.

 

Any help or pointers are appreciated.

 

Thanks

ODB

 

sfdcfoxsfdcfox

You should be able to authenticate in the constructor, and then perform a callout during each iteration of the execute function. You'll need to use a final static variable to keep the authentication key throughout the duration of the process. Take a look at the documentation for examples.

OldDeadBugOldDeadBug

 

 


sfdcfox wrote:

You should be able to authenticate in the constructor, and then perform a callout during each iteration of the execute function. You'll need to use a final static variable to keep the authentication key throughout the duration of the process. Take a look at the documentation for examples.


I have the static variable in place. added the login process to the Batch class constructor, and tried running the Analytics query in the execute section. All of that worked ok, but I still get the same error of one toomany callouts.

 

I looked through the documentation in the Batch Apex section, as well as the HTTP section of the APEX Guide and don't remember seeing any examples where a batch class was having to separate the login request from the data request, as Google Analytics apparently requires. 

 

I will certainly look again, but if you or anyone else knows where such an example is available, I would appreciate it.

 

 

Currently I'm looking at having to create an object to store the authentication token (which is supposed to be good for two weeks) from a class calling the login process where it could be accessed by a class calling the data query. I believe that would work as it would involve two independent operations, but it seems kinda dumb.

 

IF someone has an example of a batch Apex process that can both get an authentication token in one response and results from a data query in another response, I would appreciate seeing it.

OldDeadBugOldDeadBug

 


sfdcfox wrote:

You should be able to authenticate in the constructor, and then perform a callout during each iteration of the execute function. You'll need to use a final static variable to keep the authentication key throughout the duration of the process. Take a look at the documentation for examples.


 

 

Well, I thought this was taken care of.

 

I was able to authenticate in the constuctor, but I can't set a static final value in a constructor.

 

This throws an error:

 

global class Batch_runReport implements Database.Batchable<sObject>, Database.stateful, Database.AllowsCallouts
{
      static final string Token;
 
      global runReport()
      {
          Token = GACallout.authenticate();
      }
      ...
}

 

I also tried setting it directly:

 

 

global class Batch_runReport implements Database.Batchable<sObject>, Database.stateful, Database.AllowsCallouts
{
      static final string Token= GACallout.authenticate();
      string GAQuery = GACallout.getURL()
      global runReport()
      {
          
      }
      global Database.Querylocator start(Database.BatchableContext bc)
      {
	    system.debug('start method Token is '+Token);
	    return Database.getQueryLocator(GAquery);
      }
	
      global void execute(Database.BatchableContext bc, list<Campaign> CList)
      {
	    system.debug('execute token is '+Token);
	    GACaloout.runProcess(CList, Token, isTest);
      }

 ... however this now calls the authenticate process everytime the process references the Token variable, which gets me back to the original problem where the actual query doesn't go through since the execute method is now calling it when trying to send the value to the query process.

 

The Batch process as described in the Force.com guide has no mentions or examples of web callouts

The Callout section as no mentions of Batch processes.

 

Where is an example of how to do this??

How do I set a static final variable in the Batch constructor that doesn't throw an error, and remains available in the execute section??