Google Analytics: GA4 Report, Create Custom
Google Analytics: GA4 Report, Create Custom
Creates a TSV report for any Metric from Google Analytics 4 property. One Dimension and one Metric can be specified arbitrarily. Extraction filter is also available. (exact match of the Dimension value).
Configs
  • U: Select HTTP_Authz Setting *
  • A1: Set Property-ID in Google Analytics *#{EL}
  • A2: Set Metric (eg “sessions”) *#{EL}
  • A3: Set Dimension (eg “city”) *#{EL}
  • B1: Set StartDate of DateRange (Default #yesterday)#{EL}
  • B2: Set EndDate of DateRange (Default #today)#{EL}
  • B3: To filter, Set Name of Filter Dimension (eg “country”)#{EL}
  • B4: To filter, Set Match List in CSV (eg. “Japan,United States”)#{EL}
  • C1: Select NUM that stores Total (update)
  • D1: Set Number of Ranking Size (Default “20”)#{EL}
  • D2: Select STRING that stores Ranking TSV (update)
Script (click to open)
// 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 strPropertyId       = configs.get      ( "StrConfA1" );    /// REQUIRED
  if( strPropertyId     === "" ){
    throw new Error( "\n AutomatedTask ConfigError:" +
                     " Config {A1: PropertyId} must be non-empty \n" );
  }
const strMetric           = configs.get      ( "StrConfA2" );    /// REQUIRED
  if( strMetric         === "" ){
    throw new Error( "\n AutomatedTask ConfigError:" +
                     " Config {A2: Metric} must be non-empty \n" );
  }
const strDimension        = configs.get      ( "StrConfA3" );    /// REQUIRED
  if( strDimension      === "" ){
    throw new Error( "\n AutomatedTask ConfigError:" +
                     " Config {A3: Dimension} must be non-empty \n" );
  }
let   strStartDate        = configs.get      ( "StrConfB1" );    // NotRequired
  if( strStartDate      === "" ){
      strStartDate        = "yesterday";
  }else{
      strStartDate        = formatToBpmsDateStr( strStartDate );
  }
let   strEndDate          = configs.get      ( "StrConfB2" );    // NotRequired
  if( strEndDate        === "" ){
      strEndDate          = "today";
  }else{
      strEndDate          = formatToBpmsDateStr( strEndDate );
  }
let   strDimFilter        = configs.get      ( "StrConfB3" );    // NotRequired
let   strDimFilterValues  = configs.get      ( "StrConfB4" );    // NotRequired
  if( strDimFilter === "" && strDimFilterValues === "" ){
    engine.log( " AutomatedTask Config:" +
                " DimensionFilter not applied" );
  }else if( strDimFilter !== "" && strDimFilterValues !== "" ){
    engine.log( " AutomatedTask Config:" +
                " DimensionFilter: " + strDimFilter + " " + strDimFilterValues );
  }else if( strDimFilter === "" ){
    engine.log( " AutomatedTask ConfigWarning:" +
                " DimensionFilter ignored, Config {B3: DimensionName} required" );
  }else if( strDimFilterValues === "" ){
    engine.log( " AutomatedTask ConfigWarning:" +
                " DimensionFilter ignored, Config {B4: MatchList} required" );
  }else{
    throw new Error( "\n AutomatedTask Unexpected Error \n" );
  }
const numPocketTotal      = configs.getObject( "SelectConfC1" ); // 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 / 演算 ==

/// request1, prepare body
// Google Analytics > Reporting > Google Analytics Data API (GA4) > runReport
// https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/runReport
let request1Obj = {};
    request1Obj.dimensions = [];
    request1Obj.dimensions[0] = {};
    request1Obj.dimensions[0].name = strDimension;
    request1Obj.metrics = [];
    request1Obj.metrics[0] = {};
    request1Obj.metrics[0].name = strMetric;
    request1Obj.dateRanges = [];
    request1Obj.dateRanges[0] = {};
    request1Obj.dateRanges[0].startDate = strStartDate;
    request1Obj.dateRanges[0].endDate   = strEndDate;
    request1Obj.limit = numRankSize;
    if( strDimFilter !== "" && strDimFilterValues !== "" ){
      request1Obj.dimensionFilter = {};
      request1Obj.dimensionFilter.filter = {};
      request1Obj.dimensionFilter.filter.fieldName = strDimFilter;
      request1Obj.dimensionFilter.filter.inListFilter = {};
      request1Obj.dimensionFilter.filter.inListFilter.caseSensitive = true;
      request1Obj.dimensionFilter.filter.inListFilter.values =
                                                      strDimFilterValues.split(",");
    }
    request1Obj.orderBys = [];
    request1Obj.orderBys[0] = {};
    request1Obj.orderBys[0].metric = {};
    request1Obj.orderBys[0].metric.metricName = strMetric;
    request1Obj.orderBys[0].desc = true;
    request1Obj.metricAggregations = [];
    request1Obj.metricAggregations[0] = "TOTAL";

/// request1, prepare header
let request1Uri = "https://analyticsdata.googleapis.com/v1beta/properties/" +
                  strPropertyId + ":runReport";
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
const response1Obj = JSON.parse( response1Body );

/* 
engine.log( response1Body ); // debug
{
  "dimensionHeaders": [
    {
      "name": "city"
    }
  ],
  "metricHeaders": [
    {
      "name": "sessions",
      "type": "TYPE_INTEGER"
    }
  ],
  "totals": [
    {}
  ],
  "metadata": {
    "currencyCode": "JPY",
    "timeZone": "Asia/Tokyo"
  },
  "kind": "analyticsData#runReport"
}
*/

/*
{
  "dimensionHeaders": [
    {
      "name": "city"
    }
  ],
  "metricHeaders": [
    {
      "name": "sessions",
      "type": "TYPE_INTEGER"
    }
  ],
  "rows": [
    {
      "dimensionValues": [
        {
          "value": "Chiyoda City"
        }
      ],
      "metricValues": [
        {
          "value": "4137"
        }
      ]
    },
    { ... }
  ],
  "totals": [
    {
      "dimensionValues": [
        {
          "value": "RESERVED_TOTAL"
        }
      ],
      "metricValues": [
        {
          "value": "13899"
        }
      ]
    }
  ],
  "rowCount": 248,
  "metadata": {
    "currencyCode": "JPY",
    "timeZone": "Asia/Tokyo"
  },
  "kind": "analyticsData#runReport"
}
*/


let strRankTsv = "";
let numTotal = 0;

if( response1Obj.hasOwnProperty("rows") ){
  /// Create TSV by rows
  strRankTsv += strMetric + "\t" + strDimension + "\n";
  for( let i = 0; i < response1Obj.rows.length; i++ ){
    strRankTsv += response1Obj.rows[i].metricValues[0].value + "\t";
    strRankTsv += response1Obj.rows[i].dimensionValues[0].value;
    if( i !== response1Obj.rows.length - 1 ){
      strRankTsv += "\n";
    }
  }

  /// Get TOTAL
  numTotal = response1Obj.totals[0].metricValues[0].value;
}


////// == Data Updating / ワークフローデータへの代入 ==
if( numPocketTotal !== null ){
  engine.setData( numPocketTotal, new java.math.BigDecimal( numTotal ) );
}
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:
- Requests to the property (data storage) of Google Analytics when the process reaches the Automated Step.
    - You can automate the extraction work of Google Analytics Data. Analytics Reports
- Extracts via "Google Analytics Data API" for GA4 properties.
    - Data API can only be used to access GA4 properties and is not compatible with Universal Analytics.
        - As of 202204, it is a "Beta version", although "no breaking changes are expected".
        - https://developers.google.com/analytics/devguides/reporting/data/v1
    - Make sure that the Mesurement ID to be extracted is `G-XXXXXXXXXX` (GA4 property).
        - GA4 Properties is the latest version of Google Analytics released in October 2020.
        - The Mesurement ID of the UA property is `UA-XXXXXXXX-X`.
        - https://support.google.com/analytics/answer/10089681
- For GA4 properties with "Google Signals" enabled
    - "Threshold" may be applied in "Report including number of users" etc., and some data may be excluded.
        - From the viewpoint of privacy protection, it is applied when the amount of data is small. "(not set)"
    - "Do not include user attribute information" and "Extend the specified period" are effective.
    - Official Document: GA4 - Data thresholds
        - https://support.google.com/analytics/answer/9383630
- Refer to "GA4 Dimensions & Metrics Explorer" for "API Name" of metrics and dimensions.
    - https://ga-dev-tools.web.app/ga4/dimensions-metrics-explorer/
    - e.g., `sessions` by `city`
    - e.g., `screenPageViews` by `browser`
    - e.g., `conversions` by `pagePath`
    - e.g., `activeUsers` by `hostName`
    - e.g., `userEngagementDuration` by `dayOfWeek`
    - Official Document: GA4 - Dimensions and metrics
        - https://support.google.com/analytics/answer/9143382

APPENDIX
- To place this "Add-on Automated Step" on the design screen of the workflow diagram
    - Import Addon-XML (definition file of this automated step) to Workflow App in advance.
    - The system admins can also make it available in all Workflow Apps. (App-shared Add-on)
    - Manual M415: Adding an Auto-Step to be Used in a Business Process Definition
        - https://questetra.zendesk.com/hc/en-us/articles/360002247792-M415
- To activate the Workflow App including this "Add-on automated Step"
    - Authorize API communications by an authorized user in advance.
    - Enable "Google Analytics Data API" on the Google Cloud Platform
        - APIs and Services: `Google Analytics Data API`
            - https://console.cloud.google.com/project/_/apis/library
        - OFFICIAL DOCUMENT
            - https://cloud.google.com/service-usage/docs/enable-disable
    - Create an "OAuth2.0 client ID" on the Google Cloud Platform
        - Creating credentials:
            - `OAuth Client ID`
        - Application type:
            - `Web application`
        - Name:
            - `Questetra to GA4`
        - Authorized JavaScript origins:
            - `https://your-subdomain.questetra.net`
        - Authorized redirect URI:
            - `https://s.questetra.net/oauth2callback`
        - OFFICIAL DOCUMENT
            - https://cloud.google.com/endpoints/docs/frameworks/java/javascript-client
    - Set "HTTP authentication (OAuth2)" on the Questetra Workflow-App
        - Name:
            - `Questetra-GA4`
        - Authorization Endpoint URL:
            - `https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&prompt=consent`
        - Token Endpoint URL:
            - `https://oauth2.googleapis.com/token`
        - Scope:
            - `https://www.googleapis.com/auth/analytics.readonly`
        - Client ID / Consumer Secret:
            - (see above "OAuth 2.0 client ID")
        - OFFICIAL DOCUMENT
            - https://developers.google.com/identity/protocols/oauth2/web-server#httprest
- In this Add-on Automated Step, "Data API (GA4)" is used to acquire data from Google Analytics.
    - Not "Reporting API V4".
    - Not "Core Reporting API V3".
    - Requests with a response longer than 30 seconds may result in an error.
    - Detailed specifications of "Google Analytics Data API (GA4)"
        - GUIDE: Creating a Report
            - https://developers.google.com/analytics/devguides/reporting/data/v1/basics
        - REFERENCE: Method: properties.runReport
            - https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/runReport
- Can also filter the ranking list by Dimension Filter (inListFilter).
    - Only data which dimension values​exactly match any of the values will be extracted. (Case Sensitive)
        - `country`: `Canada,Japan`
        - `customEvent:locale`: `ja`
- DATE type data or DATETIME type data are also available to specify the date range.
    - `YYYY-MM-DD`, `YYYY/MM/DD`, `YYYY-MM-DD hh:mm` etc
    - Must be written in the order of Year Month Date with a delimiter.


Notes-ja:
- 案件が自動工程に到達した際、Google アナリティクスのプロパティ(データ格納庫)にリクエストします。
    - GoogleアナリティクスDataの抽出業務を自動化できます。 AnalyticsReports
- GA4プロパティ用の "Google Analytics Data API" を経由して抽出します。
    - GA4プロパティへのアクセスにのみ使用でき、UniversalAnalyticsとは互換性がありません。
        - また、202204時点において、「重大な変更は予想されていない」ものの、"Beta version" です。
        - https://developers.google.com/analytics/devguides/reporting/data/v1
    - GA4の計測IDは `G-XXXXXXXXXX` の書式になります。
        - GA4プロパティは、2020年10月にリリースされた最新版の Google アナリティクスプロパティです。
        - UAプロパティの計測IDは `UA-XXXXXXXX-X` となります。
        - https://support.google.com/analytics/answer/10089681
- "Googleシグナル" が有効となっているGA4プロパティの場合、
    - 「ユーザー数を含むレポート」等で "しきい値" が適用され、一部データが除外される場合があります。
        - 主にプライバシー保護の観点から、データ量が少ない場合に適用されます。"(not set)"
    - 「ユーザー属性情報を組み込まない」や「指定期間を長くする」といった方法が有効です。
    - 公式マニュアル: [GA4]データしきい値
        - https://support.google.com/analytics/answer/9383630
- 指標やディメンジョンの "API Name" は「GA4 Dimensions & Metrics Explorer」を参照します。
    - https://ga-dev-tools.web.app/ga4/dimensions-metrics-explorer/
    - 例) `city` ごとの `sessions` (セッション数)
    - 例) `browser` ごとの `screenPageViews` (表示回数)
    - 例) `pagePath` ごとの `conversions` (コンバージョン)
    - 例) `hostName` ごとの `activeUsers` (アクティブユーザ数)
    - 例) `dayOfWeek` (曜日) ごとの `userEngagementDuration` (フォアグラウンド秒数)
    - 公式マニュアル: [GA4]ディメンションと指標
        - https://support.google.com/analytics/answer/9143382?hl=ja

APPENDIX-ja
- この[アドオン自動工程]を、ワークフロー図の設計画面で配置(利用)できるようにするには
    - 予めアドオンXML(この自動工程の定義ファイル)を、[Workflowアプリ]に追加(アドオン)します。
    - システム管理者は、Workflow基盤の全アプリで配置できるようにすることも可能です。(アプリ共有アドオン)
    - マニュアル M415: 業務プロセス定義で利用可能な自動工程を追加する (Professional edition)
        - https://questetra.zendesk.com/hc/ja/articles/360002247792-M415
- この[アドオン自動工程]を含むワークフローアプリを、運用できるようにするには
    - あらかじめ、権限ユーザによる認可(API通信の許可)が必要です。
    - Google Cloud Platform 側で『Google Analytics Data API』を有効化する
        - APIとサービスの有効化: `Google Analytics Data API`
            - https://console.cloud.google.com/project/_/apis/library
        - 公式マニュアル: サービスの有効化と無効化
            - https://cloud.google.com/service-usage/docs/enable-disable
    - Google Cloud Platform 側で『OAuth2.0クライアントID』を作成する
        - 認証情報の作成:
            - `OAuthクライアントID`
      - アプリケーションの種類:
            - `ウェブ アプリケーション`
      - 名前:
            - `Questetra to GA4`
      - 承認済みのJavaScript生成元:
            - `https://your-subdomain.questetra.net`
      - 承認済みのリダイレクト URI:
            - `https://s.questetra.net/oauth2callback`
        - 公式マニュアル:  https://cloud.google.com/endpoints/docs/frameworks/java/javascript-client
    - Questetra 側で『"HTTP認証"(OAuth2)』を設定する
        - 名前:
            - `Questetra-GA4`
        - 認可エンドポイントURL:
            - `https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&prompt=consent`
        - トークンエンドポイントURL:
            - `https://oauth2.googleapis.com/token`
        - スコープ:
            - `https://www.googleapis.com/auth/analytics.readonly`
        - クライアントID / クライアントシークレット:
            - ( see above "OAuth 2.0 client ID" )
        - 公式マニュアル: https://developers.google.com/identity/protocols/oauth2/web-server#httprest
- この[アドオン自動工程]では、Googleアナリティクスからのデータ取得に "Data API" が利用されています。
    - "Reporting API V4" ではありません。
    - "Core Reporting API V3" ではありません。
    - レスポンスが30秒を超えるようなリクエストは、エラーになる場合があります。
    - "Google Analytics Data API (GA4)" の詳細仕様
        - GUIDE: Creating a Report
            - https://developers.google.com/analytics/devguides/reporting/data/v1/basics
        - 公式マニュアル: Method: properties.runReport
            - https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/runReport
- 完全一致リスト(inListFilter)を設定すれば、ランキングリストの絞り込みが可能です。
    - ディメンションの値がいずれかの値と完全一致するデータだけが抽出されます。(Case Sensitive)
        - `country`: `Canada,Japan`
        - `customEvent:locale`: `ja`
- 日付範囲の指定には、日付型データや日時型データなどが利用できます。
    - `YYYY-MM-DD`, `YYYY/MM/DD`, `YYYY-MM-DD hh:mm` etc
    - 区切り文字のある文字列で Year Month Date の順で表記されている必要があります。
*/

Download

2022-06-09 (C) Questetra, Inc. (MIT License)
https://support.questetra.com/addons/google-analytics-ga4-report-create-custom-2022/
The Addon-import feature is available with Professional edition.
Freely modifiable JavaScript (ECMAScript) code. No warranty of any kind.

Notes

  • Requests to the property (data storage) of Google Analytics when the process reaches the Automated Step.
    • You can automate the extraction work of Google Analytics Data. Analytics Reports
  • Extracts via “Google Analytics Data API” for GA4 properties.
  • For GA4 properties with “Google Signals” enabled
    • “Threshold” may be applied in “Report including number of users” etc., and some data may be excluded.
      • From the viewpoint of privacy protection, it is applied when the amount of data is small. “(not set)”
    • “Do not include user attribute information” and “Extend the specified period” are effective.
    • Official Document: GA4 – Data thresholds
  • Refer to “GA4 Dimensions & Metrics Explorer” for “API Name” of metrics and dimensions.

Capture

Create a TSV report for any Metric from Google Analytics 4 property. One Dimension and one Metric can be specified arbitrarily. Extraction filter is also available. (exact match of the Dimension value).

Appendix

See also

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: