// GraalJS Script (engine type: 2)
//////// START "main()" /////////////////////////////////////////////////////////////////
main();
function main(){
//// == Config Retrieving / 工程コンフィグの参照 ==
const strAuthzSetting = configs.get ( "AuthzConfU" ); /// REQUIRED
engine.log( " AutomatedTask Config: Authz Setting: " + strAuthzSetting );
const strViewId = configs.get ( "StrConfA1" ); /// REQUIRED
if( strViewId === "" ){
throw new Error( "\n AutomatedTask ConfigError:" +
" Config {A1: ViewId} is empty \n" );
}
let strStartDate = configs.get ( "StrConfB1" ); // NotRequired
if( strStartDate === "" ){
strStartDate = "today";
}else{
strStartDate = formatToBpmsDateStr( strStartDate );
}
let strEndDate = configs.get ( "StrConfB2" ); // NotRequired
if( strEndDate === "" ){
strEndDate = "today";
}else{
strEndDate = formatToBpmsDateStr( strEndDate );
}
let strFilters = configs.get ( "StrConfB3" ); // NotRequired
const numPocketPv = configs.getObject( "SelectConfC1" ); // NotRequired
const numPocketUpv = configs.getObject( "SelectConfC2" ); // NotRequired
const numPocketSes = configs.getObject( "SelectConfC3" ); // NotRequired
const numPocketEnt = configs.getObject( "SelectConfC4" ); // NotRequired
let strRankSize = configs.get ( "StrConfD1" ); // NotRequired
if( strRankSize === "" ){
strRankSize = "20";
}
let numRankSize = strRankSize - 0;
const strPocketRankTsv = configs.getObject( "SelectConfD2" ); // NotRequired
//// == Data Retrieving / ワークフローデータの参照 ==
// (Nothing. Retrieved via Expression Language in Config Retrieving)
//// == Calculating / 演算 ==
/// Google Analytics > Reporting > Reporting API v4 > batchGet
/// https://developers.google.com/analytics/devguides/reporting/core/v4/rest/v4/reports/batchGet
let request1Obj = {};
request1Obj.reportRequests = [];
request1Obj.reportRequests[0] = {};
request1Obj.reportRequests[0].viewId = strViewId;
request1Obj.reportRequests[0].dateRanges = [];
request1Obj.reportRequests[0].dateRanges[0] = {};
request1Obj.reportRequests[0].dateRanges[0].startDate = strStartDate;
request1Obj.reportRequests[0].dateRanges[0].endDate = strEndDate;
request1Obj.reportRequests[0].dimensions = [];
request1Obj.reportRequests[0].dimensions[0] = {};
request1Obj.reportRequests[0].dimensions[0].name = "ga:hostname";
request1Obj.reportRequests[0].dimensions[1] = {};
request1Obj.reportRequests[0].dimensions[1].name = "ga:pagePath";
request1Obj.reportRequests[0].dimensions[2] = {};
request1Obj.reportRequests[0].dimensions[2].name = "ga:pageTitle";
request1Obj.reportRequests[0].metrics = [];
request1Obj.reportRequests[0].metrics[0] = {};
request1Obj.reportRequests[0].metrics[0].expression = "ga:pageviews";
request1Obj.reportRequests[0].metrics[1] = {};
request1Obj.reportRequests[0].metrics[1].expression = "ga:uniquePageviews";
request1Obj.reportRequests[0].metrics[2] = {};
request1Obj.reportRequests[0].metrics[2].expression = "ga:sessions";
request1Obj.reportRequests[0].metrics[3] = {};
request1Obj.reportRequests[0].metrics[3].expression = "ga:entrances";
if( strFilters !== "" ){
request1Obj.reportRequests[0].filtersExpression = strFilters;
}
request1Obj.reportRequests[0].orderBys = [];
request1Obj.reportRequests[0].orderBys[0] = {};
request1Obj.reportRequests[0].orderBys[0].sortOrder = "DESCENDING";
request1Obj.reportRequests[0].orderBys[0].fieldName = "ga:pageviews";
request1Obj.reportRequests[0].orderBys[1] = {};
request1Obj.reportRequests[0].orderBys[1].sortOrder = "DESCENDING";
request1Obj.reportRequests[0].orderBys[1].fieldName = "ga:uniquePageviews";
request1Obj.reportRequests[0].orderBys[2] = {};
request1Obj.reportRequests[0].orderBys[2].sortOrder = "DESCENDING";
request1Obj.reportRequests[0].orderBys[2].fieldName = "ga:entrances";
request1Obj.reportRequests[0].pageSize = numRankSize;
let request1Uri = "https://analyticsreporting.googleapis.com/v4/reports:batchGet";
let request1 = httpClient.begin(); // HttpRequestWrapper
request1 = request1.authSetting( strAuthzSetting ); // with "Authorization: Bearer XX"
// https://questetra.zendesk.com/hc/en-us/articles/360024574471-R2300#HttpRequestWrapper
request1 = request1.body( JSON.stringify( request1Obj ), "application/json" );
// request1, try
const response1 = request1.post( request1Uri ); // HttpResponseWrapper
engine.log( " AutomatedTask ApiRequest1 Start: " + request1Uri );
const response1Code = response1.getStatusCode() + "";
const response1Body = response1.getResponseAsString() + "";
engine.log( " AutomatedTask ApiResponse Status: " + response1Code );
if( response1Code !== "200"){
throw new Error( "\n AutomatedTask UnexpectedResponseError: " +
response1Code + "\n" + response1Body + "\n" );
}
// response1, parse
/*
engine.log( response1Body ); // debug
{
"reports": [
{
"columnHeader": {
"dimensions": [
"ga:hostname",
"ga:pagePath",
"ga:pageTitle"
],
"metricHeader": {
"metricHeaderEntries": [
{
"name": "ga:pageviews",
"type": "INTEGER"
},
{
"name": "ga:uniquePageviews",
"type": "INTEGER"
},
{
"name": "ga:sessions",
"type": "INTEGER"
},
{
"name": "ga:entrances",
"type": "INTEGER"
}
]
}
},
"data": {
"rows": [
{
"dimensions": [
"example.questetra.net",
"/PE/Workitem/Form/normalIframe.iframe",
"マイタスク すべてのアプリ ワークフロー - Questetra BPM Suite"
],
"metrics": [
{
"values": [
"32",
"9",
"1",
"1"
]
}
]
},
{
"dimensions": [
"example.questetra.net",
"/PE/Workitem/Form/saveIframe.iframe",
"マイタスク すべてのアプリ ワークフロー - Questetra BPM Suite"
],
"metrics": [
{
"values": [
"26",
"7",
"1",
"1"
]
}
]
},
{ . . . },
{
"dimensions": [
"example.questetra.net",
"/System/Event/MessageStartForm/9999/8/kTaR9XXXXX2jwFqYYYYYO84ByR2sHe7t/view",
"Basic Trial"
],
"metrics": [
{
"values": [
"5",
"1",
"0",
"0"
]
}
]
}
],
"totals": [
{
"values": [ "358", "182", "39", "39" ]
}
],
"rowCount": 86,
"minimums": [
{
"values": [ "1", "1", "0", "0" ]
}
],
"maximums": [
{
"values": [ "32", "16", "16", "16" ]
}
]
},
"nextPageToken": "20"
}
]
}
*/
const response1Obj = JSON.parse( response1Body );
/// Create TSV
let strRankTsv = "";
if( response1Obj.reports[0].data.hasOwnProperty("rows") ){
strRankTsv += "PV" + "\t" + "UPV" + "\t" + "SS" + "\t" + "ENT" + "\t" + "URI" + "\t" + "TITLE" + "\n";
for( let i = 0; i < response1Obj.reports[0].data.rows.length; i++ ){
strRankTsv += response1Obj.reports[0].data.rows[i].metrics[0].values[0] + "\t";
strRankTsv += response1Obj.reports[0].data.rows[i].metrics[0].values[1] + "\t";
strRankTsv += response1Obj.reports[0].data.rows[i].metrics[0].values[2] + "\t";
strRankTsv += response1Obj.reports[0].data.rows[i].metrics[0].values[3] + "\t";
strRankTsv += response1Obj.reports[0].data.rows[i].dimensions[0];
strRankTsv += response1Obj.reports[0].data.rows[i].dimensions[1] + "\t";
strRankTsv += response1Obj.reports[0].data.rows[i].dimensions[2];
if( i !== response1Obj.reports[0].data.rows.length - 1 ){
strRankTsv += "\n";
}
}
}
/// Get Result
let numPv = response1Obj.reports[0].data.totals[0].values[0];
let numUpv = response1Obj.reports[0].data.totals[0].values[1];
let numSes = response1Obj.reports[0].data.totals[0].values[2];
let numEnt = response1Obj.reports[0].data.totals[0].values[3];
//// == Data Updating / ワークフローデータへの代入 ==
if( numPocketPv !== null ){
engine.setData( numPocketPv, new java.math.BigDecimal( numPv ) );
}
if( numPocketUpv !== null ){
engine.setData( numPocketUpv, new java.math.BigDecimal( numUpv ) );
}
if( numPocketSes !== null ){
engine.setData( numPocketSes, new java.math.BigDecimal( numSes ) );
}
if( numPocketEnt !== null ){
engine.setData( numPocketEnt, new java.math.BigDecimal( numEnt ) );
}
if( strPocketRankTsv !== null ){
engine.setData( strPocketRankTsv, strRankTsv );
}
} //////// END "main()" /////////////////////////////////////////////////////////////////
function formatToBpmsDateStr( str ) { // Format from DateStr to "DateStr for Bpms"
if( str === "" ){
throw new Error( "\n AutomatedTask ParseDateError:" +
" String is empty \n" );
}
var arrNumParts = str.match( /\d+/g );
if( arrNumParts === null ){
throw new Error( "\n AutomatedTask ParseDateError:" +
" No numeric characters in: " + str + "\n" );
}
if( arrNumParts.length < 3){
throw new Error( "\n AutomatedTask ParseDateError:" +
" 3 Parts of numeric characters are needed in: " + str + "\n" );
}
let strNew = arrNumParts[0] + "-" +
( '0' + arrNumParts[1] ).slice(-2) + "-" +
( '0' + arrNumParts[2] ).slice(-2);
return strNew;
}
/*
Notes:
- When the process reaches this automated task, the data in G-Analytics is automatically extracted.
- The unit of ranking aggregation "Dimension" is the following three.
- Hostname (`ga:hostname`)
- Page (`ga:pagePath`)
- PageName(`ga:pageTitle`)
- The following four indicators "Metrics" are aggregated.
- Number of page views (`ga:pageviews`)
- Number of sessions (`ga:uniquePageviews`)
- @Number of sessions (`ga:sessions`)
- Number of times visitors (`ga:entrances`)
- Difference between Entrances and Sessions
- https://support.google.com/analytics/answer/2956047
APPENDIX
- This add-on acquire data from Google Analytics using "Reporting API V4".
- Not "Data API V1 (Beta)".
- Not "Core Reporting API V3".
- A request with a response longer than 30 seconds may result in an error.
- You can narrow down the ranking list by filtersExpression.
- Filtering by Dimension also reduces the total value.
- The filter by Metric narrows down only the ranking list.
- e.g.
- `ga:timeOnPage>10`
- `ga:country==Canada`
- `ga:browser!=Firefox`
- `ga:pagePath=@/ja/`
- `ga:hostname==#{#q_Platform_ID}.questetra.net`
- https://developers.google.com/analytics/devguides/reporting/core/v3/reference#filters
- https://ga-dev-tools.web.app/dimensions-metrics-explorer/
- You can use date type data or datetime type data to specify the date range.
- `YYYY-MM-DD`, `YYYY/MM/DD`,` YYYY-MM-DD hh:mm` etc
- It must be a delimited string in the order Year Month Date.
- Setting example of "HTTP Authentication" (OAuth2)
- Authorization Endpoint URL:
- https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force
- Token Endpoint URL:
- https://accounts.google.com/o/oauth2/token
- Scope:
- https://www.googleapis.com/auth/analytics.readonly
- Client ID, Consumer Secret:
- ( from https://console.developers.google.com/ )
- Redirect URLs: https://s.questetra.net/oauth2callback
Notes-ja:
- 案件がこの自動工程に到達した際、Googleアナリティクス内のデータを自動抽出します。 AnalyticsReports
- ランキング集計の単位〔ディメンジョン〕は、以下の3つです。
- ホスト名(`ga:hostname`)
- ページ(`ga:pagePath`)
- ページ名(`ga:pageTitle`)
- 集計対象となる指標〔メトリックス〕は、以下の4つです
- ページビュー数(`ga:pageviews`)
- ページ別訪問数(`ga:uniquePageviews`)
- #セッション数(`ga:sessions`)
- 閲覧開始数(`ga:entrances`)
- ※閲覧開始数とセッション数の違い
- https://support.google.com/analytics/answer/2956047
APPENDIX-ja
- 本アドオンでは、Googleアナリティクスからのデータ取得に "Reporting API V4" が利用されています。
- "Data API V1 (Beta)" ではありません。
- "Core Reporting API V3" ではありません。
- レスポンスが30秒を超えるようなリクエストは、エラーになる場合があります。
- 抽出フィルタ式(filtersExpression)を設定すれば、ランキングリストの絞り込みが可能です。
- ディメンジョン〔Dimension〕によるフィルタは、合計値も減少します。
- 指標〔Metric〕によるフィルタは、ランキングリストだけが絞り込まれます。
- 例
- `ga:timeOnPage>10`
- `ga:country==Canada`
- `ga:browser!=Firefox`
- `ga:pagePath=@/ja/`
- `ga:hostname==#{#q_Platform_ID}.questetra.net`
- https://developers.google.com/analytics/devguides/reporting/core/v3/reference#filters
- https://ga-dev-tools.web.app/dimensions-metrics-explorer/
- 日付範囲の指定には、日付型データや日時型データなどが利用できます。
- `YYYY-MM-DD`, `YYYY/MM/DD`, `YYYY-MM-DD hh:mm` etc
- 区切り文字のある文字列で Year Month Date の順で表記されている必要があります。
- "HTTP認証"(OAuth2)の設定例
- Authorization Endpoint URL:
- https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force
- Token Endpoint URL:
- https://accounts.google.com/o/oauth2/token
- Scope:
- https://www.googleapis.com/auth/analytics.readonly
- Client ID, Consumer Secret:
- ( from https://console.developers.google.com/ )
- Redirect URLs: https://s.questetra.net/oauth2callback
*/
Pingback: Google Analytics Reports (PV ranking) – Questetra Support