# AppFlow Custom Connector for Google Analytics 4 (GA4) ## æ¦‚è¦ æœ¬ã‚µãƒ³ãƒ—ãƒ«ã¯ Google Analytics 4 (GA4) ã‹ã‚‰ãƒ‹ã‚¢ãƒªã‚¢ãƒ«ã‚¿ã‚¤ãƒ ã§ãƒ‡ãƒ¼ã‚¿ã‚’é€ä¿¡ã™ã‚‹ AppFlow カスタムコãƒã‚¯ã‚¿ã§ã™ã€‚日次ã§ã®ãƒ‡ãƒ¼ã‚¿å–å¾—ã«ã¤ã„ã¦ã¯ã€ãƒã‚¤ãƒ†ã‚£ãƒ–ã«[サãƒãƒ¼ãƒˆã—ã¦ã„ã‚‹ Google Analytics 4 コãƒã‚¯ã‚¿](https://docs.aws.amazon.com/appflow/latest/userguide/connectors-google-analytics-4.html)ã®æ´»ç”¨ã‚‚ä½µã›ã¦æ¤œè¨Žãã ã•ã„。ã¾ãŸã€Custom Connector SDK を用ã„ãŸå®Ÿè£…ã«ã¤ã„ã¦ã¯ã“ã¡ã‚‰ã®[解説ブãƒã‚°](https://aws.amazon.com/jp/builders-flash/202302/appflow-custom-connecter-saas-data)ã‚‚ä½µã›ã¦ã”å‚ç…§ãã ã•ã„。 ## 目次 - [デプãƒã‚¤æ‰‹é †](/docs/DEPLOYMENT.md) - [動作確èªæ‰‹é †](/docs/OPERATION.md) - [カスタムコãƒã‚¯ã‚¿ã«ã¤ã„ã¦](#カスタムコãƒã‚¯ã‚¿) ## カスタムコãƒã‚¯ã‚¿ Custom Connector SDK ã®ä»•æ§˜ã«ã¤ã„ã¦èª¬æ˜Žã—ã¾ã™ã€‚本サンプルã§ã¯ [Amazon AppFlow Custom Connector SDK for Python](https://github.com/awslabs/aws-appflow-custom-connector-python) を使用ã—ã¦ã„ã¾ã™ã€‚ カスタムコãƒã‚¯ã‚¿ã‚’利用ã™ã‚‹ã«ã¯ã“ã¡ã‚‰ã® SDK を用ã„ã¦ã€ã‚«ã‚¹ã‚¿ãƒ コãƒã‚¯ã‚¿ç”¨ã® Lambda を実装ã—デプãƒã‚¤ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ãã—ã¦ã€ãƒ‡ãƒ—ãƒã‚¤ã—㟠Lambda 関数を AppFlow コンソールã‹ã‚‰ã‚«ã‚¹ã‚¿ãƒ コãƒã‚¯ã‚¿ã¨ã—ã¦ç™»éŒ²ã—ã€åˆ©ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ ### カスタムコãƒã‚¯ã‚¿ç”¨ Lambda 関数 以下㮠3 ã¤ã® Class ã¨å„ Class 内ã§æ±ºã¾ã£ãŸé–¢æ•°ã‚’実装ã—ã€å„関数ã®ãƒ¬ã‚¹ãƒãƒ³ã‚¹ã¯ AppFlow ã®æ±ºã¾ã£ãŸå½¢ã§è¿”ã™å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚[å„関数ã®è©³ç´°](#å„関数ã®è©³ç´°)ã¯å¾Œè¿°ã—ã¾ã™ã€‚ - ConfigurationHandler - validate_connector_runtime_settings - validate_credentials - describe_connector_configuration - RecordHandler - retrieve_data - write_data - query_data - MetadataHandler - list_entities - describe_entity #### 注æ„äº‹é … - Lambda 関数ã«ä»¥ä¸‹ã®ãƒªã‚½ãƒ¼ã‚¹ãƒ™ãƒ¼ã‚¹ãƒãƒªã‚·ãƒ¼ã‚’付与ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ ```json { "Version": "2012-10-17", "Id": "default", "Statement": [ { "Sid": "<ä»»æ„ã®åå‰>", "Effect": "Allow", "Principal": { "Service": "appflow.amazonaws.com" }, "Action": "lambda:InvokeFunction", "Resource": "arn:aws:lambda:<リージョンå>:<アカウントID>:function:<Lambda関数å>", "Condition": { "ArnLike": { "AWS:SourceArn": "arn:aws:appflow:<リージョンå>:<アカウントID>:*" } } } ] } ``` - フãƒãƒ¼å®Ÿè¡Œæ™‚以外(カスタムコãƒã‚¯ã‚¿ç™»éŒ²æ™‚ã€ãƒ•ãƒãƒ¼ä½œæˆæ™‚ãªã©ï¼‰ã§ã‚‚ Lambda 関数ã¯å®Ÿè¡Œã•ã‚Œã‚‹ã®ã§ CloudWatch Logs ã‚’å‚ç…§ã—ã¦ãƒ‡ãƒãƒƒã‚°å¯èƒ½ã§ã™ã€‚ - カスタムコãƒã‚¯ã‚¿ã¨ã—㦠Lambda 関数を登録ã—ãŸå¾Œä¸”ã¤ã€ãƒ•ãƒãƒ¼ä½œæˆã®å®Œäº†å‰ã« Lambda 関数を更新ã—ãŸå ´åˆã¯ã‚«ã‚¹ã‚¿ãƒ コãƒã‚¯ã‚¿ã®ç™»éŒ²ã‹ã‚‰ã‚„ã‚Šç›´ã™å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã¾ãŸã€ãƒ•ãƒãƒ¼ä½œæˆã¾ã§å®Œäº†ã™ã‚‹ã¨ Lambda ã®æ›´æ–°ã¯ãƒ•ãƒãƒ¼ã«å³æ™‚åæ˜ ã•ã‚Œã‚‹ãŸã‚ã€å†ç™»éŒ²ã¯ä¸è¦ã§ã™ã€‚ ### å„関数ã®è©³ç´° #### describe_connector_configuration - カスタムコãƒã‚¯ã‚¿ç™»éŒ²æ™‚ã«å‘¼ã³å‡ºã•ã‚Œã€é€£æºå…ƒã‚·ã‚¹ãƒ†ãƒ ã¸ã®èªè¨¼æ–¹æ³•ã®å®šç¾©ã‚’返㙠- é¸æŠžå¯èƒ½ãªèªè¨¼æ–¹å¼ - OAuth2 - BASIC - API ã‚ー - カスタムèªè¨¼ #### list_entities - フãƒãƒ¼ä½œæˆæ™‚ã«å‘¼ã³å‡ºã•ã‚Œã€ã‚¹ã‚ーマ定義 (Entity) ã®ãƒªã‚¹ãƒˆã‚’返㙠- Entity - サãƒãƒ¼ãƒˆã™ã‚‹ API 毎ã«å®šç¾©ã™ã‚‹ - RunRealtimeReport API ã®ä¾‹ - ```python run_realtime_report_entity = context.Entity( entity_identifier="RunRealtimeReportEntity", label="RunRealtimeReportEntity", has_nested_entities=False, description="RunRealtimeReportEntity", ) ``` - `has_nested_entities` ã¯ã‚µãƒ–オブジェクトã®æœ‰ç„¡ - 返り値㮠`entities` ã« `Entity` ã®ãƒªã‚¹ãƒˆã‚’渡㙠#### describe_entity - フãƒãƒ¼ä½œæˆã®ãƒ‡ãƒ¼ã‚¿ãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰ãƒžãƒƒãƒ”ングã§å‘¼ã³å‡ºã•ã‚Œã€ãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰ã®å®šç¾©ã‚’返㙠- 返り値㮠`entity_definition` - entity 㯠`list_entities` ã® `entities` ã®å½“該 `Entity` ã¨åŒå€¤ - `fields` ã¯å½“該 `Entity` ã®ãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰å®šç¾©ã®ãƒªã‚¹ãƒˆ - `field_name`, `data_type`, `read_properties` ãªã©ã‚’è¨å®š - `data_time` フィールドã®ä¾‹ - ```python date_time_field = context.FieldDefinition( field_name="DateTime", data_type=fields.FieldDataType.String, data_type_label="string", label="DateTime", description="DateTime", default_value="1970-01-01 00:00:00", is_primary_key=True, # データã®é€ä¿¡å…ƒã«æŒ‡å®šã™ã‚‹å ´åˆã«è¨å®šã™ã‚‹ãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰ã®åž‹å®šç¾© read_properties=fields.ReadOperationProperty( # データå–得時ã«ãƒ•ã‚£ãƒ«ã‚¿ã¨ã—ã¦æŒ‡å®šã§ãã‚‹é …ç›®ã‹ã©ã†ã‹ is_queryable=True, # データå–得時ã«è¡¨ç¤ºã•ã‚Œã‚‹ã‹ã©ã†ã‹ is_retrievable=True, # null 値を許容ã™ã‚‹ã‹ã©ã†ã‹ is_nullable=False, # Date ã‹ DateTime åž‹ã‹ã©ã†ã‹ is_timestamp_field_for_incremental_queries=False, ), # データã®é€ä¿¡å…ˆã«æŒ‡å®šã™ã‚‹å ´åˆã«è¨å®šã™ã‚‹ãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰ã®åž‹å®šç¾© write_properties=None, ) ``` #### query_data - フãƒãƒ¼å®Ÿè¡Œæ™‚ã«å‘¼ã³å‡ºã•ã‚Œã€ãƒ•ãƒãƒ¼ã§å®šç¾©ã•ã‚ŒãŸãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰ã‚’å–å¾—ã™ã‚‹ - 返り値㮠`records` ã«æ¸¡ã™é…列ã¯ä»¥ä¸‹ã®å½¢å¼ã® JSON オブジェクトã®æ–‡å—列ã®é…列 - ```python record_list = [ '{"field-name-1": 1, "field-name-2": 2, "field-name-3": 3}', '{"field-name-1": 4, "field-name-2": 5, "field-name-3": 6}', ] ``` - `field-name-*` ã¯å„フィールド㮠`describe_entity` ã® `field_name` ã¨ä¸€è‡´ã•ã›ã‚‹ - é€ä¿¡ãƒ‡ãƒ¼ã‚¿ã® `field` ã‚’ `field-name-1` ã«æŒ‡å®šã—ãŸå ´åˆã€S3 ã«æ ¼ç´ã•ã‚Œã‚‹ã®ã¯ä»¥ä¸‹ã®ãƒ‡ãƒ¼ã‚¿ - ``` {"field-name-1":1} {"field-name-1":4} ``` ## 本カスタムコãƒã‚¯ã‚¿ã®æ³¨æ„äº‹é … 本カスタムコãƒã‚¯ã‚¿ã¯ runRealtimeReport API ã«ã‚ˆã‚Š GA4 ã®ãƒ‡ãƒ¼ã‚¿ã‚’å–å¾—ã—ã€ãã‚Œã«ã‚ˆã‚Šã„ãã¤ã‹ã®åˆ¶ç´„ãŒã‚ã‚‹ãŸã‚注æ„äº‹é …ã¨ã—ã¦èª¬æ˜Žã—ã¾ã™ã€‚runRealtimeReport API ã®è©³ç´°ã«ã¤ã„ã¦ã¯ GA4 ã®ãƒ‰ã‚ュメントをæ£å¼ãªæƒ…å ±ã¨ã™ã‚‹ã®ã§ãã¡ã‚‰ã‚’å‚ç…§ã„ãŸã ãã€æœ¬ã‚»ã‚¯ã‚·ãƒ§ãƒ³ã®å†…容ã¯å‚è€ƒæƒ…å ±ã¨ã—ã¦ã„ãŸã ã‘ã‚Œã°ã¨æ€ã„ã¾ã™ã€‚ ### 相対的ãªæ—¥æ™‚ã®å–得制é™ã«ã‚ˆã‚‹æ—¥æ™‚データã®èª¤å·® 日時データã¯ç›¸å¯¾å€¤ã§è¿”ã•ã‚Œã‚‹ãŸã‚ (datetime ã§ã¯ãªã minutesAgo) ã€ã“ã®ç›¸å¯¾å€¤ã¨ãƒãƒ¼ã‚«ãƒ«ã®ç¾åœ¨æ—¥æ™‚ã‹ã‚‰å®Ÿéš›ã®æ—¥æ™‚データã«è¿‘ã„値をå–å¾—ã— `DateTime` ã¨ã—ã¦ã„ã¾ã™ã€‚ ### 最大å–得行数ã®åˆ¶é™ å–å¾—ã™ã‚‹è¡Œæ•°ã«ã¯ 100,000 件ã®åˆ¶é™ãŒã‚ã‚Šã€dimensions ã®å€¤ã‚’増やã™ã¨å–å¾—ã™ã‚‹è¡Œæ•°ãŒå¤§å¹…ã«å¢—åŠ ã—ã¾ã™ã€‚ã“ã®ãŸã‚ã€è¨ªå•è€…ãŒå¤šã dimensions も多ã„å ´åˆã€ã“ã®åˆ¶é™ã«é”ã—ã¦ã—ã¾ã„æ£ç¢ºãªãƒ‡ãƒ¼ã‚¿ãŒå–å¾—ã§ããªã„å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ページãƒãƒ¼ã‚·ãƒ§ãƒ³ãªã©ã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ãŠã‚‰ãšã€åˆ¶é™ã«é”ã™ã‚‹å ´åˆã¯æŒ‡å®šã™ã‚‹ dimensions を減らã™å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ ## Security See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information. ## License This library is licensed under the MIT-0 License. See the LICENSE file.