Hello,
I have followed the guide at https://kumarvikram.com/google-analytics-report-v4-csharp-console-app/ to create a C# script to get data using Google Analytics Reporting V4 API. The guide is written as a C# console program, but I am using SSIS to try to accomplish
the same results using a Script Task.
I have done the prerequisities needed to fetch data from Google Analytics Reporting, such as creating a service account and granting it read & analyze permission at Google Analytics.
When I try to execute the package I get the error "Cannot execute script because the script entry point is invalid".
What I have tried
Seeing as I have copied a C# console code into a SSIS Script Task, I have gathered that some of the autogenerated code in C# is neccessary.I have therefore deleted the old script task, and made a new one with the auto generated C# code intact.I have read that this is a common cause of the issue.
I have looked into the settings of the script task and I have tried to use entry point valueMain and ScriptMain, both to no avail.
I have seen that using System.Configuration requires you to add a reference to System.Configuration even though it does not give you errors when you do not have it referenced in the project.I have added a reference to System.Configuration.
I can confirm that the SQL Server Target under project is SQL Server 2016, which is the SQL Server version used.
The code itself when I edit the script task is distributed among three files in the project. I have added a new XML file to the project, which I named App.config which consists of the following code:
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
configuration
>
<
appSettings
>
<
add
key
=
"KeyFileName"
value
=
"Your key file name here"
/>
<
add
key
=
"ViewId"
value
=
"Your ViewId here"
/>
</
appSettings
>
<
startup
>
<
supportedRuntime
version
=
"v4.0"
sku
=
".NETFramework,Version=v4.5.2"
/>
</
startup
>
</
configuration
>
I have a new Code File named ReportManager.cs looking like this:
using
Google.Apis.AnalyticsReporting.v4;
using
Google.Apis.AnalyticsReporting.v4.Data;
using
Google.Apis.Auth.OAuth2;
using
Google.Apis.Services;
using
System.Configuration;
using
System.IO;
namespace
GAReportExtractor.App
{
public
class
ReportManager
{
/// <summary>
/// Intializes and returns Analytics Reporting Service Instance using the parameters stored in key file
/// </summary>
/// <param name="keyFileName"></param>
/// <returns></returns>
private
static
AnalyticsReportingService GetAnalyticsReportingServiceInstance(
string
keyFileName)
{
string
[] scopes = { AnalyticsReportingService.Scope.AnalyticsReadonly };
//Read-only access to Google Analytics
GoogleCredential credential;
using
(
var
stream =
new
FileStream(keyFileName, FileMode.Open, FileAccess.Read))
{
credential = GoogleCredential.FromStream(stream).CreateScoped(scopes);
}
// Create the Analytics service.
return
new
AnalyticsReportingService(
new
BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName =
"GA Reporting data extraction example"
,
});
}
/// <summary>
/// Fetches all required reports from Google Analytics
/// </summary>
/// <param name="reportRequests"></param>
/// <returns></returns>
public
static
GetReportsResponse GetReport(GetReportsRequest getReportsRequest)
{
var
analyticsService = GetAnalyticsReportingServiceInstance(ConfigurationManager.AppSettings[
"KeyFileName"
]);
return
analyticsService.Reports.BatchGet(getReportsRequest).Execute();
}
}
}
and lastly I have the ScriptMain.cs file:
using
Google.Apis.AnalyticsReporting.v4.Data;
using
System;
using
System.Collections.Generic;
using
System.Configuration;
using
System.Linq;
namespace
GAReportExtractor.App
{
[Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.RunTime.DTSExecResult.Sucess,
Failure = Microsoft.SqlServer.Dts.RunTime.DTSExecResult.Failure
};
static
void
Main(
string
[] args)
{
try
{
#region Prepare Report Request object
// Create the DateRange object. Here we want data from last week.
var
dateRange =
new
DateRange
{
StartDate = DateTime.UtcNow.AddDays(-7).ToString(
"yyyy-MM-dd"
),
EndDate = DateTime.UtcNow.ToString(
"yyyy-MM-dd"
)
};
// Create the Metrics and dimensions object.
var
metrics =
new
List<Metric> {
new
Metric { Expression =
"ga:sessions"
, Alias =
"Sessions"
} };
var
dimensions =
new
List<Dimension> {
new
Dimension { Name =
"ga:pageTitle"
} };
//Get required View Id from configuration
var
ViewId = ConfigurationManager.AppSettings[
"ViewId"
];
// Create the Request object.
var
reportRequest =
new
ReportRequest
{
DateRanges =
new
List<DateRange> { dateRange },
Metrics = metrics,
Dimensions = dimensions,
ViewId = ViewId
};
var
getReportsRequest =
new
GetReportsRequest();
getReportsRequest.ReportRequests =
new
List<ReportRequest> { reportRequest };
#endregion
//Invoke Google Analytics API call and get report
var
response = ReportManager.GetReport(getReportsRequest);
//Print report data to console
PrintReport(response);
}
catch
(Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
Console.ReadLine();
}
}
private
static
void
PrintReport(GetReportsResponse response)
{
foreach
(
var
report
in
response.Reports)
{
var
rows = report.Data.Rows;
ColumnHeader header = report.ColumnHeader;
var
dimensionHeaders = header.Dimensions;
var
metricHeaders = header.MetricHeader.MetricHeaderEntries;
if
(!rows.Any())
{
Console.WriteLine(
"No data found!"
);
return
;
}
else
{
foreach
(
var
row
in
rows)
{
var
dimensions = row.Dimensions;
var
metrics = row.Metrics;
for
(
int
i = 0; i < dimensionHeaders.Count && i < dimensions.Count; i++)
{
Console.WriteLine(dimensionHeaders[i] +
": "
+ dimensions[i]);
}
for
(
int
j = 0; j < metrics.Count; j++)
{
DateRangeValues values = metrics[j];
for
(
int
k = 0; k < values.Values.Count && k < metricHeaders.Count; k++)
{
Console.WriteLine(metricHeaders[k].Name +
": "
+ values.Values[k]);
}
}
}
}
}
}
}
}