Reading results and handling errors
RetrieveData works asynchronously: it sends the request and returns
immediately, then raises OnRetrieveData when rows arrive or
OnRetrieveDataError when the request fails. This chapter explains the shape of
the returned data, how to read it in the result handler, the limits that cause
errors, and a complete live-dashboard example that ties authentication,
requesting, and reading together.
The result structure
Results land in Data. Its Data list holds one entry per result row, and each
row is a TTMSFNCCloudGoogleAnalyticsStringArray — an array of column values as
strings. Columns appear in the order the metrics and dimensions were requested,
so a request for smSessions with tdDate and udUserType yields rows of three
columns: session count, date, and user type. Use Data.Data.Count for the row
count and Length(Row) for the column count; convert numeric metric strings with
StrToFloatDot when you need values rather than text.
Reading rows in the result handler
Read Data inside OnRetrieveData; that handler runs once the rows are
available. Pair it with OnRetrieveDataError so transport failures and rejected
requests surface to the user instead of failing silently.
procedure TForm1.AnalyticsRetrieveData(Sender: TObject;
const ARequestResult: TTMSFNCCloudBaseRequestResult);
var
Row: TTMSFNCCloudGoogleAnalyticsStringArray;
I, J: Integer;
begin
// Data.Data holds one entry per result row; each row is an array of column values
// in the order the metrics and dimensions were requested.
for I := 0 to FAnalytics.Data.Data.Count - 1 do
begin
Row := FAnalytics.Data.Data[I];
for J := 0 to Length(Row) - 1 do
Memo1.Lines.Add(Row[J]);
end;
end;
procedure TForm1.AnalyticsRetrieveDataError(Sender: TObject; const AError: string);
begin
// Fires for transport errors and for metric/dimension limit violations.
ShowMessage('Analytics error: ' + AError);
end;
Limits and the ErrorMessages property
Analytics caps how many metrics and dimensions one request may combine. When a
request exceeds those limits the component reports the problem through
OnRetrieveDataError rather than returning rows. The ErrorMessages property
holds the text used for those metric and dimension limit messages, so you can
localize or reword them. If a report comes back empty or errors out, trim the
number of requested categories first — that is the most common cause.
Putting it together: a live dashboard
This capstone combines all three chapters: it connects with persisted tokens,
builds a realtime request once OnConnected confirms the tokens are valid, and
prints each returned row in OnRetrieveData. Drive it from a timer that calls
RetrieveData on an interval to keep the dashboard current.
procedure TForm1.StartDashboard;
begin
FAnalytics := TTMSFNCCloudGoogleAnalytics.Create(Self);
FAnalytics.Authentication.ClientID := '<your-client-id>.apps.googleusercontent.com';
FAnalytics.Authentication.Secret := '<your-client-secret>';
FAnalytics.Authentication.CallBackURL := 'http://127.0.0.1:8888';
FAnalytics.PersistTokens.Location := plIniFile;
FAnalytics.PersistTokens.Key := TTMSFNCUtils.AddBackslash(TTMSFNCUtils.GetDocumentsPath)
+ FAnalytics.ClassName + '.ini';
FAnalytics.LoadTokens;
FAnalytics.ViewID := '<your-view-id>';
FAnalytics.OnConnected := DashboardConnected;
FAnalytics.OnRetrieveData := DashboardData;
FAnalytics.OnRetrieveDataError := DashboardError;
FAnalytics.Connect;
end;
procedure TForm1.DashboardConnected(Sender: TObject);
var
Metrics: TTMSFNCCloudGoogleAnalyticsRealtimeMetricsArray;
GeoDims: TTMSFNCCloudGoogleAnalyticsRealtimeGeoDimensionArray;
begin
// Build the request only once the connection (and tokens) are confirmed.
SetLength(Metrics, 1);
Metrics[0] := rtActiveUsers;
SetLength(GeoDims, 2);
GeoDims[0] := rtgdCountry;
GeoDims[1] := rtgdCity;
FAnalytics.RequestData.RealtimeMetrics := Metrics;
FAnalytics.RequestData.RealtimeGeoDimension := GeoDims;
FAnalytics.RetrieveData;
end;
procedure TForm1.DashboardData(Sender: TObject;
const ARequestResult: TTMSFNCCloudBaseRequestResult);
var
I: Integer;
begin
for I := 0 to FAnalytics.Data.Data.Count - 1 do
Memo1.Lines.Add(string.Join(' | ', FAnalytics.Data.Data[I]));
end;
procedure TForm1.DashboardError(Sender: TObject; const AError: string);
begin
Memo1.Lines.Add('Error: ' + AError);
end;
Common mistakes
- Reading
DataoutsideOnRetrieveData. The call is asynchronous; the rows are only guaranteed to be present inside the handler. - Requesting too many categories at once. Exceeding the metric or dimension limit produces an error instead of data — reduce the request.
- Forgetting to reset previous selections.
RequestDatakeeps its arrays between calls, so clear the categories you no longer want before reissuing. - A stale or empty
ViewID. Requests target the configured reporting view; an unset or wrongViewIDreturns no usable rows.
See also
- Authentication and connecting — establish the connection first.
- Building report requests — choose metrics and dimensions.
- API reference — full class reference.