airbyte-source-google-ads 4.1.4__py3-none-any.whl → 4.1.4.dev202511261224__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {airbyte_source_google_ads-4.1.4.dist-info → airbyte_source_google_ads-4.1.4.dev202511261224.dist-info}/METADATA +2 -2
- {airbyte_source_google_ads-4.1.4.dist-info → airbyte_source_google_ads-4.1.4.dev202511261224.dist-info}/RECORD +7 -7
- source_google_ads/components.py +0 -12
- source_google_ads/manifest.yaml +45 -129
- source_google_ads/source.py +6 -0
- {airbyte_source_google_ads-4.1.4.dist-info → airbyte_source_google_ads-4.1.4.dev202511261224.dist-info}/WHEEL +0 -0
- {airbyte_source_google_ads-4.1.4.dist-info → airbyte_source_google_ads-4.1.4.dev202511261224.dist-info}/entry_points.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: airbyte-source-google-ads
|
|
3
|
-
Version: 4.1.4
|
|
3
|
+
Version: 4.1.4.dev202511261224
|
|
4
4
|
Summary: Source implementation for Google Ads.
|
|
5
5
|
Home-page: https://airbyte.com
|
|
6
6
|
License: Elv2
|
|
@@ -11,7 +11,7 @@ Classifier: License :: Other/Proprietary License
|
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.10
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
-
Requires-Dist: airbyte-cdk (>=7.
|
|
14
|
+
Requires-Dist: airbyte-cdk (>=7.4.1,<8.0.0)
|
|
15
15
|
Requires-Dist: google-ads (==27.0.0)
|
|
16
16
|
Requires-Dist: pendulum (<3.0.0)
|
|
17
17
|
Requires-Dist: protobuf (==4.25.2)
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
source_google_ads/__init__.py,sha256=Nlo5H6LlaSgg7tx_LyqMIy3MXiAagfk3izZ9o44VvSE,1201
|
|
2
|
-
source_google_ads/components.py,sha256=
|
|
2
|
+
source_google_ads/components.py,sha256=_Jku4_NHRg4OzYSmtk23H0LfYo0bbqfx1navUoUztug,40970
|
|
3
3
|
source_google_ads/config_migrations.py,sha256=oBi_qNqBpLS8GNCaIOBo0stNdYuyqVl6lkrhdXRwMX8,4405
|
|
4
4
|
source_google_ads/google_ads.py,sha256=cxS18tz0fFJjmIhlhFQ3Zvu2K8bhDtmsl1kFeO7nNhk,11595
|
|
5
|
-
source_google_ads/manifest.yaml,sha256=
|
|
5
|
+
source_google_ads/manifest.yaml,sha256=ICDxfH8-pT78PfQwU2h_mgCVkv-sSzuQBR4BdnVZEpU,219342
|
|
6
6
|
source_google_ads/models.py,sha256=ZmdS3z_2roaEQgV2Mx1CDm33MztpQ66SfHDzP8XwZog,1658
|
|
7
7
|
source_google_ads/run.py,sha256=ydIyq_vSNV5Z4mJYnsO5GyNDsLDd0qibBsq6wnvuFAo,2002
|
|
8
8
|
source_google_ads/schemas/customer_client.json,sha256=oThcyUDO1yWpxtWPWdoAFqTXEIweF8N4q6mRI73Q6yU,984
|
|
9
9
|
source_google_ads/schemas/service_accounts.json,sha256=HVSyzbEoxzB4rntRHOjAh0ZYgbR584ew0W0CdJH7ECU,3485
|
|
10
|
-
source_google_ads/source.py,sha256=
|
|
10
|
+
source_google_ads/source.py,sha256=xmfWTrefFYNDm8Nl5FUqnTByjgQTcJI6VVBD_khY6No,1791
|
|
11
11
|
source_google_ads/spec.json,sha256=8hbc7smbaffIkYCkX2BYJLB9kgaH8vYKCg-H0y1FvUs,7810
|
|
12
12
|
source_google_ads/streams.py,sha256=FB-DNJlXhjQADptT-wrv3iGWoliyRuvDuHGeqiN9HsY,13349
|
|
13
13
|
source_google_ads/utils.py,sha256=-KpgGv2W8WueXvGRC3xbVreDl5-5-vU9OwzC5SZDKVc,21409
|
|
14
|
-
airbyte_source_google_ads-4.1.4.dist-info/METADATA,sha256=
|
|
15
|
-
airbyte_source_google_ads-4.1.4.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
16
|
-
airbyte_source_google_ads-4.1.4.dist-info/entry_points.txt,sha256=pP4Llir93XGkHFDZfXXxK7qOWo9_U1ssCJToyxEUB4w,63
|
|
17
|
-
airbyte_source_google_ads-4.1.4.dist-info/RECORD,,
|
|
14
|
+
airbyte_source_google_ads-4.1.4.dev202511261224.dist-info/METADATA,sha256=hF_jEn4xE6E4jWFnE9O0bCHOBI4rFJPegmqUH9JdhPc,5376
|
|
15
|
+
airbyte_source_google_ads-4.1.4.dev202511261224.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
16
|
+
airbyte_source_google_ads-4.1.4.dev202511261224.dist-info/entry_points.txt,sha256=pP4Llir93XGkHFDZfXXxK7qOWo9_U1ssCJToyxEUB4w,63
|
|
17
|
+
airbyte_source_google_ads-4.1.4.dev202511261224.dist-info/RECORD,,
|
source_google_ads/components.py
CHANGED
|
@@ -697,7 +697,6 @@ class CustomGAQueryHttpRequester(HttpRequester):
|
|
|
697
697
|
def __post_init__(self, parameters: Mapping[str, Any]):
|
|
698
698
|
super().__post_init__(parameters=parameters)
|
|
699
699
|
self.query = GAQL.parse(parameters.get("query"))
|
|
700
|
-
self.stream_response = True
|
|
701
700
|
|
|
702
701
|
@staticmethod
|
|
703
702
|
def is_metrics_in_custom_query(query: GAQL) -> bool:
|
|
@@ -762,17 +761,6 @@ class CustomGAQueryHttpRequester(HttpRequester):
|
|
|
762
761
|
return self.query[from_index + 4 :].strip()
|
|
763
762
|
|
|
764
763
|
|
|
765
|
-
class CustomGAQueryClickViewHttpRequester(CustomGAQueryHttpRequester):
|
|
766
|
-
@staticmethod
|
|
767
|
-
def _insert_segments_date_expr(query: GAQL, start_date: str, end_date: str) -> GAQL:
|
|
768
|
-
if "segments.date" not in query.fields:
|
|
769
|
-
query = query.append_field("segments.date")
|
|
770
|
-
condition = f"segments.date ='{start_date}'"
|
|
771
|
-
if query.where:
|
|
772
|
-
return query.set_where(query.where + " AND " + condition)
|
|
773
|
-
return query.set_where(condition)
|
|
774
|
-
|
|
775
|
-
|
|
776
764
|
@dataclass()
|
|
777
765
|
class CustomGAQuerySchemaLoader(SchemaLoader):
|
|
778
766
|
"""
|
source_google_ads/manifest.yaml
CHANGED
|
@@ -65,15 +65,27 @@ definitions:
|
|
|
65
65
|
field_path:
|
|
66
66
|
- results
|
|
67
67
|
|
|
68
|
+
cursor_paginator:
|
|
69
|
+
type: DefaultPaginator
|
|
70
|
+
pagination_strategy:
|
|
71
|
+
type: CursorPagination
|
|
72
|
+
cursor_value: "{{ response.get('nextPageToken', '') }}"
|
|
73
|
+
stop_condition: "{{ response.get('nextPageToken', '') is none }}"
|
|
74
|
+
page_token_option:
|
|
75
|
+
type: RequestOption
|
|
76
|
+
inject_into: body_json
|
|
77
|
+
field_path: ["page_token"]
|
|
78
|
+
|
|
68
79
|
base_retriever:
|
|
69
80
|
type: SimpleRetriever
|
|
70
81
|
requester:
|
|
71
82
|
$ref: "#/definitions/stream_requester"
|
|
72
83
|
record_selector:
|
|
73
84
|
$ref: "#/definitions/base_selector"
|
|
85
|
+
paginator:
|
|
86
|
+
$ref: "#/definitions/cursor_paginator"
|
|
74
87
|
decoder:
|
|
75
|
-
type:
|
|
76
|
-
class_name: "source_google_ads.components.GoogleAdsStreamingDecoder"
|
|
88
|
+
type: JsonDecoder
|
|
77
89
|
|
|
78
90
|
stream_base:
|
|
79
91
|
type: DeclarativeStream
|
|
@@ -187,7 +199,7 @@ definitions:
|
|
|
187
199
|
$ref: "#/schemas"
|
|
188
200
|
authenticator:
|
|
189
201
|
$ref: "#/definitions/authenticator"
|
|
190
|
-
url_base: "https://googleads.googleapis.com/v20/{{ stream_partition['customer_id'] }}/googleAds:
|
|
202
|
+
url_base: "https://googleads.googleapis.com/v20/{{ stream_partition['customer_id'] }}/googleAds:search"
|
|
191
203
|
http_method: POST
|
|
192
204
|
error_handler:
|
|
193
205
|
$ref: "#/definitions/base_error_handler"
|
|
@@ -212,7 +224,7 @@ definitions:
|
|
|
212
224
|
incremental_stream:
|
|
213
225
|
$ref: "#/definitions/incremental_stream_base"
|
|
214
226
|
$parameters:
|
|
215
|
-
url_base: "https://googleads.googleapis.com/v20/{{ stream_partition['parent_slice']['customer_id'] }}/googleAds:
|
|
227
|
+
url_base: "https://googleads.googleapis.com/v20/{{ stream_partition['parent_slice']['customer_id'] }}/googleAds:search"
|
|
216
228
|
retriever:
|
|
217
229
|
type: CustomRetriever
|
|
218
230
|
class_name: "source_google_ads.components.CriterionRetriever"
|
|
@@ -228,6 +240,8 @@ definitions:
|
|
|
228
240
|
http_method: POST
|
|
229
241
|
error_handler:
|
|
230
242
|
$ref: "#/definitions/base_error_handler"
|
|
243
|
+
paginator:
|
|
244
|
+
$ref: "#/definitions/cursor_paginator"
|
|
231
245
|
record_selector:
|
|
232
246
|
type: RecordSelector
|
|
233
247
|
extractor:
|
|
@@ -283,6 +297,8 @@ definitions:
|
|
|
283
297
|
$ref: "#/definitions/base_requester"
|
|
284
298
|
url_base: "https://googleads.googleapis.com/v20/customers:listAccessibleCustomers"
|
|
285
299
|
http_method: GET
|
|
300
|
+
paginator:
|
|
301
|
+
type: NoPagination
|
|
286
302
|
record_selector:
|
|
287
303
|
extractor:
|
|
288
304
|
type: CustomRecordExtractor
|
|
@@ -406,6 +422,11 @@ definitions:
|
|
|
406
422
|
parent_key: "clientCustomer"
|
|
407
423
|
partition_field: "customer_id"
|
|
408
424
|
stream: "#/definitions/customer_client"
|
|
425
|
+
decoder:
|
|
426
|
+
type: CustomDecoder
|
|
427
|
+
class_name: "source_google_ads.components.GoogleAdsStreamingDecoder"
|
|
428
|
+
paginator:
|
|
429
|
+
type: NoPagination
|
|
409
430
|
transformations:
|
|
410
431
|
- type: CustomTransformation
|
|
411
432
|
class_name: "source_google_ads.components.KeysToSnakeCaseGoogleAdsTransformation"
|
|
@@ -466,6 +487,13 @@ definitions:
|
|
|
466
487
|
|
|
467
488
|
ad_group_ad_stream:
|
|
468
489
|
$ref: "#/definitions/incremental_stream_base"
|
|
490
|
+
retriever:
|
|
491
|
+
$ref: "#/definitions/incremental_stream_base/retriever"
|
|
492
|
+
paginator:
|
|
493
|
+
type: NoPagination
|
|
494
|
+
decoder:
|
|
495
|
+
type: CustomDecoder
|
|
496
|
+
class_name: "source_google_ads.components.GoogleAdsStreamingDecoder"
|
|
469
497
|
name: ad_group_ad
|
|
470
498
|
primary_key:
|
|
471
499
|
- ad_group.id
|
|
@@ -637,10 +665,12 @@ definitions:
|
|
|
637
665
|
$ref: "#/schemas/click_view"
|
|
638
666
|
authenticator:
|
|
639
667
|
$ref: "#/definitions/authenticator"
|
|
640
|
-
url_base: "https://googleads.googleapis.com/v20/{{ stream_partition['customer_id'] }}/googleAds:
|
|
668
|
+
url_base: "https://googleads.googleapis.com/v20/{{ stream_partition['customer_id'] }}/googleAds:search"
|
|
641
669
|
http_method: POST
|
|
642
670
|
error_handler:
|
|
643
671
|
$ref: "#/definitions/base_error_handler"
|
|
672
|
+
paginator:
|
|
673
|
+
$ref: "#/definitions/cursor_paginator"
|
|
644
674
|
incremental_sync:
|
|
645
675
|
type: DatetimeBasedCursor
|
|
646
676
|
cursor_field: segments.date
|
|
@@ -829,6 +859,8 @@ definitions:
|
|
|
829
859
|
error_handler:
|
|
830
860
|
$ref: "#/definitions/base_error_handler"
|
|
831
861
|
name: change_status
|
|
862
|
+
paginator:
|
|
863
|
+
$ref: "#/definitions/cursor_paginator"
|
|
832
864
|
pagination_reset:
|
|
833
865
|
type: PaginationReset
|
|
834
866
|
action: SPLIT_USING_CURSOR
|
|
@@ -998,6 +1030,14 @@ definitions:
|
|
|
998
1030
|
)
|
|
999
1031
|
}}
|
|
1000
1032
|
create_or_update: true
|
|
1033
|
+
- type: ComponentMappingDefinition
|
|
1034
|
+
field_path:
|
|
1035
|
+
- retriever
|
|
1036
|
+
- requester
|
|
1037
|
+
- $parameters
|
|
1038
|
+
- query
|
|
1039
|
+
value: "{{ components_values.get('query', None) }}"
|
|
1040
|
+
create_or_update: true
|
|
1001
1041
|
- type: ComponentMappingDefinition
|
|
1002
1042
|
field_path:
|
|
1003
1043
|
- retriever
|
|
@@ -1045,130 +1085,6 @@ definitions:
|
|
|
1045
1085
|
)
|
|
1046
1086
|
}}
|
|
1047
1087
|
create_or_update: true
|
|
1048
|
-
- type: ComponentMappingDefinition
|
|
1049
|
-
field_path:
|
|
1050
|
-
- incremental_sync
|
|
1051
|
-
- step
|
|
1052
|
-
value: "P1D"
|
|
1053
|
-
condition: >-
|
|
1054
|
-
{{
|
|
1055
|
-
(
|
|
1056
|
-
(
|
|
1057
|
-
components_values.get('query', '').count('segments.date') == 1
|
|
1058
|
-
and (components_values.get('query') | regex_search('(?i)(\\bSELECT\\b[\\s\\S]*?segments\\.date[\\s\\S]*?\\bFROM\\b)'))
|
|
1059
|
-
)
|
|
1060
|
-
or
|
|
1061
|
-
(
|
|
1062
|
-
components_values.get('query', '').count('segments.date') == 2
|
|
1063
|
-
and (components_values.get('query') | regex_search('(?i)(\\bSELECT\\b[\\s\\S]*?segments\\.date[\\s\\S]*?\\bFROM\\b)'))
|
|
1064
|
-
and (components_values.get('query') | regex_search('(?i)(\\bORDER\\s+BY\\b[\\s\\S]*?segments\\.date)'))
|
|
1065
|
-
)
|
|
1066
|
-
) and components_values.get('query', '') | regex_search('(?i)(\\bFROM\\s+click_view\\b)')
|
|
1067
|
-
}}
|
|
1068
|
-
create_or_update: true
|
|
1069
|
-
- type: ComponentMappingDefinition
|
|
1070
|
-
field_path:
|
|
1071
|
-
- incremental_sync
|
|
1072
|
-
- start_datetime
|
|
1073
|
-
value: >-
|
|
1074
|
-
{
|
|
1075
|
-
"type": "MinMaxDatetime",
|
|
1076
|
-
"datetime": "{{ max(config.get('start_date', day_delta(-90, format='%Y-%m-%d')), day_delta(-90, format='%Y-%m-%d')) }}",
|
|
1077
|
-
"datetime_format": "%Y-%m-%d"
|
|
1078
|
-
}
|
|
1079
|
-
condition: >-
|
|
1080
|
-
{{
|
|
1081
|
-
(
|
|
1082
|
-
(
|
|
1083
|
-
components_values.get('query', '').count('segments.date') == 1
|
|
1084
|
-
and (components_values.get('query') | regex_search('(?i)(\\bSELECT\\b[\\s\\S]*?segments\\.date[\\s\\S]*?\\bFROM\\b)'))
|
|
1085
|
-
)
|
|
1086
|
-
or
|
|
1087
|
-
(
|
|
1088
|
-
components_values.get('query', '').count('segments.date') == 2
|
|
1089
|
-
and (components_values.get('query') | regex_search('(?i)(\\bSELECT\\b[\\s\\S]*?segments\\.date[\\s\\S]*?\\bFROM\\b)'))
|
|
1090
|
-
and (components_values.get('query') | regex_search('(?i)(\\bORDER\\s+BY\\b[\\s\\S]*?segments\\.date)'))
|
|
1091
|
-
)
|
|
1092
|
-
) and components_values.get('query', '') | regex_search('(?i)(\\bFROM\\s+click_view\\b)')
|
|
1093
|
-
}}
|
|
1094
|
-
create_or_update: true
|
|
1095
|
-
- type: ComponentMappingDefinition
|
|
1096
|
-
field_path:
|
|
1097
|
-
- incremental_sync
|
|
1098
|
-
- end_datetime
|
|
1099
|
-
value: >-
|
|
1100
|
-
{
|
|
1101
|
-
"type": "MinMaxDatetime",
|
|
1102
|
-
"datetime": "{{ format_datetime((str_to_datetime(config.get('end_date')) if config.get('end_date') else now_utc()) + duration('P1D'), '%Y-%m-%d') }}",
|
|
1103
|
-
"datetime_format": "%Y-%m-%d"
|
|
1104
|
-
}
|
|
1105
|
-
condition: >-
|
|
1106
|
-
{{
|
|
1107
|
-
(
|
|
1108
|
-
(
|
|
1109
|
-
components_values.get('query', '').count('segments.date') == 1
|
|
1110
|
-
and (components_values.get('query') | regex_search('(?i)(\\bSELECT\\b[\\s\\S]*?segments\\.date[\\s\\S]*?\\bFROM\\b)'))
|
|
1111
|
-
)
|
|
1112
|
-
or
|
|
1113
|
-
(
|
|
1114
|
-
components_values.get('query', '').count('segments.date') == 2
|
|
1115
|
-
and (components_values.get('query') | regex_search('(?i)(\\bSELECT\\b[\\s\\S]*?segments\\.date[\\s\\S]*?\\bFROM\\b)'))
|
|
1116
|
-
and (components_values.get('query') | regex_search('(?i)(\\bORDER\\s+BY\\b[\\s\\S]*?segments\\.date)'))
|
|
1117
|
-
)
|
|
1118
|
-
) and components_values.get('query', '') | regex_search('(?i)(\\bFROM\\s+click_view\\b)')
|
|
1119
|
-
}}
|
|
1120
|
-
create_or_update: true
|
|
1121
|
-
- type: ComponentMappingDefinition
|
|
1122
|
-
field_path:
|
|
1123
|
-
- incremental_sync
|
|
1124
|
-
- cursor_granularity
|
|
1125
|
-
value: P1D
|
|
1126
|
-
condition: >-
|
|
1127
|
-
{{
|
|
1128
|
-
(
|
|
1129
|
-
(
|
|
1130
|
-
components_values.get('query', '').count('segments.date') == 1
|
|
1131
|
-
and (components_values.get('query') | regex_search('(?i)(\\bSELECT\\b[\\s\\S]*?segments\\.date[\\s\\S]*?\\bFROM\\b)'))
|
|
1132
|
-
)
|
|
1133
|
-
or
|
|
1134
|
-
(
|
|
1135
|
-
components_values.get('query', '').count('segments.date') == 2
|
|
1136
|
-
and (components_values.get('query') | regex_search('(?i)(\\bSELECT\\b[\\s\\S]*?segments\\.date[\\s\\S]*?\\bFROM\\b)'))
|
|
1137
|
-
and (components_values.get('query') | regex_search('(?i)(\\bORDER\\s+BY\\b[\\s\\S]*?segments\\.date)'))
|
|
1138
|
-
)
|
|
1139
|
-
) and components_values.get('query', '') | regex_search('(?i)(\\bFROM\\s+click_view\\b)')
|
|
1140
|
-
}}
|
|
1141
|
-
create_or_update: true
|
|
1142
|
-
- type: ComponentMappingDefinition
|
|
1143
|
-
field_path:
|
|
1144
|
-
- retriever
|
|
1145
|
-
- requester
|
|
1146
|
-
- class_name
|
|
1147
|
-
value: "source_google_ads.components.CustomGAQueryClickViewHttpRequester"
|
|
1148
|
-
condition: >-
|
|
1149
|
-
{{
|
|
1150
|
-
(
|
|
1151
|
-
(
|
|
1152
|
-
components_values.get('query', '').count('segments.date') == 1
|
|
1153
|
-
and (components_values.get('query') | regex_search('(?i)(\\bSELECT\\b[\\s\\S]*?segments\\.date[\\s\\S]*?\\bFROM\\b)'))
|
|
1154
|
-
)
|
|
1155
|
-
or
|
|
1156
|
-
(
|
|
1157
|
-
components_values.get('query', '').count('segments.date') == 2
|
|
1158
|
-
and (components_values.get('query') | regex_search('(?i)(\\bSELECT\\b[\\s\\S]*?segments\\.date[\\s\\S]*?\\bFROM\\b)'))
|
|
1159
|
-
and (components_values.get('query') | regex_search('(?i)(\\bORDER\\s+BY\\b[\\s\\S]*?segments\\.date)'))
|
|
1160
|
-
)
|
|
1161
|
-
) and components_values.get('query', '') | regex_search('(?i)(\\bFROM\\s+click_view\\b)')
|
|
1162
|
-
}}
|
|
1163
|
-
create_or_update: true
|
|
1164
|
-
- type: ComponentMappingDefinition
|
|
1165
|
-
field_path:
|
|
1166
|
-
- retriever
|
|
1167
|
-
- requester
|
|
1168
|
-
- $parameters
|
|
1169
|
-
- query
|
|
1170
|
-
value: "{{ components_values.get('query', None) }}"
|
|
1171
|
-
create_or_update: true
|
|
1172
1088
|
- type: ComponentMappingDefinition
|
|
1173
1089
|
field_path:
|
|
1174
1090
|
- retriever
|
source_google_ads/source.py
CHANGED
|
@@ -34,6 +34,12 @@ class SourceGoogleAds(YamlDeclarativeSource):
|
|
|
34
34
|
config["customer_ids"] = config["customer_id"].split(",")
|
|
35
35
|
config.pop("customer_id")
|
|
36
36
|
|
|
37
|
+
# Replace tabs with spaces in custom queries to prevent YAML parsing errors
|
|
38
|
+
if "custom_queries_array" in config:
|
|
39
|
+
for query_config in config["custom_queries_array"]:
|
|
40
|
+
if "query" in query_config and isinstance(query_config["query"], str):
|
|
41
|
+
query_config["query"] = query_config["query"].replace("\t", " ")
|
|
42
|
+
|
|
37
43
|
return config
|
|
38
44
|
|
|
39
45
|
def streams(self, config: Mapping[str, Any]) -> List[Stream]:
|
|
File without changes
|