From be65546cd6421d959954164a6fd120a7cfbcea01 Mon Sep 17 00:00:00 2001 From: marcosmarxm Date: Tue, 27 Sep 2022 15:15:57 -0300 Subject: [PATCH] format connector --- .../integration_tests/acceptance.py | 2 +- .../connectors/source-dv-360/main.py | 2 +- .../connectors/source-dv-360/setup.py | 12 +- .../source-dv-360/source_dv_360/fields.py | 1091 +++++++++-------- .../source-dv-360/source_dv_360/source.py | 110 +- .../source-dv-360/source_dv_360/streams.py | 622 +++++----- .../source-dv-360/unit_tests/conftest.py | 4 +- .../source-dv-360/unit_tests/test_fields.py | 31 +- .../source-dv-360/unit_tests/test_source.py | 45 +- .../source-dv-360/unit_tests/test_streams.py | 160 ++- .../source-dv-360/unit_tests/unit_test.py | 2 +- 11 files changed, 1046 insertions(+), 1035 deletions(-) diff --git a/airbyte-integrations/connectors/source-dv-360/integration_tests/acceptance.py b/airbyte-integrations/connectors/source-dv-360/integration_tests/acceptance.py index 4b6c44dfc613..34f2f625e15b 100644 --- a/airbyte-integrations/connectors/source-dv-360/integration_tests/acceptance.py +++ b/airbyte-integrations/connectors/source-dv-360/integration_tests/acceptance.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2021 Airbyte, Inc., all rights reserved. +# Copyright (c) 2022 Airbyte, Inc., all rights reserved. # diff --git a/airbyte-integrations/connectors/source-dv-360/main.py b/airbyte-integrations/connectors/source-dv-360/main.py index 7657cfebe4e4..2f4395facd43 100644 --- a/airbyte-integrations/connectors/source-dv-360/main.py +++ b/airbyte-integrations/connectors/source-dv-360/main.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2021 Airbyte, Inc., all rights reserved. +# Copyright (c) 2022 Airbyte, Inc., all rights reserved. # diff --git a/airbyte-integrations/connectors/source-dv-360/setup.py b/airbyte-integrations/connectors/source-dv-360/setup.py index c2be031b12fb..bc2f7e3986eb 100644 --- a/airbyte-integrations/connectors/source-dv-360/setup.py +++ b/airbyte-integrations/connectors/source-dv-360/setup.py @@ -1,19 +1,13 @@ # -# Copyright (c) 2021 Airbyte, Inc., all rights reserved. +# Copyright (c) 2022 Airbyte, Inc., all rights reserved. # from setuptools import find_packages, setup -MAIN_REQUIREMENTS = [ - "airbyte-cdk~=0.1","google-api-python-client" -] +MAIN_REQUIREMENTS = ["airbyte-cdk~=0.1", "google-api-python-client"] -TEST_REQUIREMENTS = [ - "pytest~=6.1", - "source-acceptance-test", - "pytest-mock" -] +TEST_REQUIREMENTS = ["pytest~=6.1", "source-acceptance-test", "pytest-mock"] setup( name="source_dv_360", diff --git a/airbyte-integrations/connectors/source-dv-360/source_dv_360/fields.py b/airbyte-integrations/connectors/source-dv-360/source_dv_360/fields.py index cc6fffd8f0e9..f5d8dc12a2e9 100644 --- a/airbyte-integrations/connectors/source-dv-360/source_dv_360/fields.py +++ b/airbyte-integrations/connectors/source-dv-360/source_dv_360/fields.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2021 Airbyte, Inc., all rights reserved. +# Copyright (c) 2022 Airbyte, Inc., all rights reserved. # @@ -7,550 +7,551 @@ def sanitize(s): - s = re.sub('[&]', 'and', s) - s = re.sub('[%]', 'pct', s) - s = re.sub('[\s/-]+', '_', s.strip()) - # Remove punctuation, which is anything that is not either a word or a whitespace character - s = re.sub('[^\w\s]+', '', s) - return s.lower() + s = re.sub(r"[&]", "and", s) + s = re.sub(r"[%]", "pct", s) + s = re.sub(r"[\s/-]+", "_", s.strip()) + # Remove punctuation, which is anything that is not either a word or a whitespace character + s = re.sub(r"[^\w\s]+", "", s) + return s.lower() + # Mapping betwee naming in the connector and naming in the report builder API_REPORT_BUILDER_MAPPING = { - "audience_list":"FILTER_AUDIENCE_LIST", - "date":"FILTER_DATE", - "eligible_cookies_on_first_party_audience_list":"FILTER_ELIGIBLE_COOKIES_ON_FIRST_PARTY_AUDIENCE_LIST", - "eligible_cookies_on_third_party_audience_list_and_interest":"FILTER_ELIGIBLE_COOKIES_ON_THIRD_PARTY_AUDIENCE_LIST_AND_INTEREST", - "first_party_audience_list":"FILTER_USER_LIST_FIRST_PARTY_NAME", - "first_party_audience_list_cost":"FILTER_FIRST_PARTY_AUDIENCE_LIST_COST", - "first_party_audience_list_id":"FILTER_USER_LIST_FIRST_PARTY", - "first_party_audience_list_type":"FILTER_FIRST_PARTY_AUDIENCE_LIST_TYPE", - "match_ratio":"FILTER_MATCH_RATIO", - "third_party_audience_list":"FILTER_USER_LIST_THIRD_PARTY_NAME", - "third_party_audience_list_cost":"FILTER_THIRD_PARTY_AUDIENCE_LIST_COST", - "third_party_audience_list_id":"FILTER_USER_LIST_THIRD_PARTY", - "third_party_audience_list_type":"FILTER_THIRD_PARTY_AUDIENCE_LIST_TYPE", - "advertiser":"FILTER_ADVERTISER_NAME", - "advertiser_currency":"FILTER_ADVERTISER_CURRENCY", - "advertiser_id":"FILTER_ADVERTISER", - "advertiser_integration_code":"FILTER_ADVERTISER_INTEGRATION_CODE", - "advertiser_status":"FILTER_ADVERTISER_INTEGRATION_STATUS", - "advertiser_time_zone":"FILTER_ADVERTISER_TIMEZONE", - "app_url":"FILTER_APP_URL", - "app_url_excluded":"FILTER_APP_URL_EXCLUDED", - "app_url_id":"FILTER_SITE_ID", - "campaign":"FILTER_MEDIA_PLAN_NAME", - "campaign_id":"FILTER_MEDIA_PLAN", - "category":"FILTER_PAGE_CATEGORY", - "cm_placement_id":"FILTER_CM_PLACEMENT_ID", - "creative":"FILTER_CREATIVE", - "creative_asset":"FILTER_CREATIVE_ASSET", - "creative_attributes":"FILTER_CREATIVE_ATTRIBUTE", - "creative_height":"FILTER_CREATIVE_HEIGHT", - "creative_id":"FILTER_CREATIVE_ID", - "creative_integration_code":"FILTER_CREATIVE_INTEGRATION_CODE", - "creative_rendered_in_amp":"FILTER_CREATIVE_RENDERED_IN_AMP", - "creative_size":"FILTER_CREATIVE_SIZE", - "creative_source":"FILTER_CREATIVE_SOURCE", - "creative_status":"FILTER_CREATIVE_STATUS", - "creative_type":"FILTER_CREATIVE_TYPE", - "creative_width":"FILTER_CREATIVE_WIDTH", - "day_of_week":"FILTER_DAY_OF_WEEK", - "exchange":"FILTER_EXCHANGE", - "exchange_code":"FILTER_EXCHANGE_CODE", - "exchange_id":"FILTER_EXCHANGE_ID", - "floodlight_activity":"FILTER_FLOODLIGHT_ACTIVITY", - "floodlight_activity_id":"FILTER_FLOODLIGHT_ACTIVITY_ID", - "insertion_order":"FILTER_INSERTION_ORDER_NAME", - "insertion_order_integration_code":"FILTER_INSERTION_ORDER_INTEGRATION_CODE", - "insertion_order_status":"FILTER_INSERTION_ORDER_STATUS", - "line_item":"FILTER_LINE_ITEM_NAME", - "line_item_id":"FILTER_LINE_ITEM", - "line_item_integration_code":"FILTER_LINE_ITEM_INTEGRATION_CODE", - "line_item_status":"FILTER_LINE_ITEM_STATUS", - "line_item_type":"FILTER_LINE_ITEM_TYPE", - "month":"FILTER_MONTH", - "order_id":"FILTER_ORDER_ID", - "partner":"FILTER_PARTNER_NAME", - "partner_currency":"FILTER_PARTNER_CURRENCY", - "partner_id":"FILTER_PARTNER", - "partner_status":"FILTER_PARTNER_STATUS", - "targeted_data_providers":"FILTER_TARGETED_DATA_PROVIDERS", - "year":"FILTER_YEAR", - "country":"FILTER_COUNTRY", - "country_id":"FILTER_COUNTRY_ID", - "insertion_order_id":"FILTER_INSERTION_ORDER", - "inventory_source":"FILTER_INVENTORY_SOURCE_NAME", - "active_view_custom_metric_id":"FILTER_ACTIVE_VIEW_CUSTOM_METRIC_ID", - "active_view_custom_metric_name":"FILTER_ACTIVE_VIEW_CUSTOM_METRIC_NAME", - "ad_position":"FILTER_AD_POSITION", - "ad_type":"FILTER_AD_TYPE", - "algorithm":"FILTER_ALGORITHM", - "algorithm_id":"FILTER_ALGORITHM_ID", - "amp_page_request":"FILTER_AMP_PAGE_REQUEST", - "attributed_userlist":"FILTER_ATTRIBUTED_USERLIST", - "attributed_userlist_cost":"FILTER_ATTRIBUTED_USERLIST_COST", - "attributed_userlist_id":"FILTER_TARGETED_USER_LIST", - "attributed_userlist_type":"FILTER_ATTRIBUTED_USERLIST_TYPE", - "attribution_model":"FILTER_ATTRIBUTION_MODEL", - "audience_list_cost":"FILTER_AUDIENCE_LIST_COST", - "audience_list_id":"FILTER_USER_LIST", - "audience_list_type":"FILTER_AUDIENCE_LIST_TYPE", - "audience_name":"FILTER_AUDIENCE_NAME", - "audience_type":"FILTER_AUDIENCE_TYPE", - "authorized_seller_state":"FILTER_AUTHORIZED_SELLER_STATE", - "billable_outcome":"FILTER_BILLABLE_OUTCOME", - "brand_lift_type":"FILTER_BRAND_LIFT_TYPE", - "browser_id":"FILTER_BROWSER", - "budget_segment_description":"FILTER_BUDGET_SEGMENT_DESCRIPTION", - "channel":"FILTER_CHANNEL_NAME", - "channel_id":"FILTER_CHANNEL_ID", - "channel_type":"FILTER_CHANNEL_TYPE", - "city":"FILTER_CITY_NAME", - "city_id":"FILTER_CITY", - "companion_creative":"FILTER_COMPANION_CREATIVE_NAME", - "companion_creative_id":"FILTER_COMPANION_CREATIVE_ID", - "companion_creative_size":"FILTER_COMPANION_CREATIVE_SIZE", - "data_provider":"FILTER_DATA_PROVIDER_NAME", - "data_provider_id":"FILTER_DATA_PROVIDER", - "detailed_demographics":"FILTER_DETAILED_DEMOGRAPHICS", - "detailed_demographics_id":"FILTER_DETAILED_DEMOGRAPHICS_ID", - "device":"FILTER_DEVICE", - "device_make":"FILTER_DEVICE_MAKE", - "device_model":"FILTER_DEVICE_MODEL", - "device_type":"FILTER_DEVICE_TYPE", - "digital_content_label":"FILTER_DIGITAL_CONTENT_LABEL", - "dma":"FILTER_DMA_NAME", - "dma_code":"FILTER_DMA", - "extension":"FILTER_EXTENSION", - "extension_status":"FILTER_EXTENSION_STATUS", - "extension_type":"FILTER_EXTENSION_TYPE", - "format":"FILTER_FORMAT", - "gmail_age":"FILTER_GMAIL_AGE", - "gmail_city":"FILTER_GMAIL_CITY", - "gmail_country":"FILTER_GMAIL_COUNTRY", - "gmail_device_type":"FILTER_GMAIL_DEVICE_TYPE", - "gmail_gender":"FILTER_GMAIL_GENDER", - "gmail_region":"FILTER_GMAIL_REGION", - "gmail_remarketing_list":"FILTER_GMAIL_REMARKETING_LIST", - "household_income":"FILTER_HOUSEHOLD_INCOME", - "impression_counting_method":"FILTER_IMPRESSION_COUNTING_METHOD", - "insertion_order_daily_frequency":"FILTER_CAMPAIGN_DAILY_FREQUENCY", - "interest":"FILTER_INTEREST", - "inventory_commitment_type":"FILTER_INVENTORY_COMMITMENT_TYPE", - "inventory_delivery_method":"FILTER_INVENTORY_DELIVERY_METHOD", - "inventory_rate_type":"FILTER_INVENTORY_RATE_TYPE", - "inventory_source_group":"FILTER_INVENTORY_SOURCE_GROUP", - "inventory_source_group_id":"FILTER_INVENTORY_SOURCE_GROUP_ID", - "inventory_source_id":"FILTER_INVENTORY_SOURCE_ID", - "inventory_source_id_external":"FILTER_INVENTORY_SOURCE_EXTERNAL_ID", - "inventory_source_type":"FILTER_INVENTORY_SOURCE_TYPE", - "isp_or_carrier":"FILTER_CARRIER_NAME", - "isp_or_carrier_id":"FILTER_CARRIER", - "keyword":"FILTER_KEYWORD", - "life_event":"FILTER_LIFE_EVENT", - "life_events":"FILTER_LIFE_EVENTS", - "line_item_daily_frequency":"FILTER_LINE_ITEM_DAILY_FREQUENCY", - "line_item_lifetime_frequency":"FILTER_LINE_ITEM_LIFETIME_FREQUENCY", - "max_video_duration":"FILTER_VIDEO_DURATION_SECONDS", - "measurement_source":"FILTER_MEASUREMENT_SOURCE", - "operating_system":"FILTER_OS", - "platform":"FILTER_PLATFORM", - "playback_method":"FILTER_PLAYBACK_METHOD", - "position_in_content":"FILTER_POSITION_IN_CONTENT", - "public_inventory":"FILTER_PUBLIC_INVENTORY", - "publisher_property":"FILTER_PUBLISHER_PROPERTY", - "publisher_property_id":"FILTER_PUBLISHER_PROPERTY_ID", - "publisher_property_section":"FILTER_PUBLISHER_PROPERTY_SECTION", - "publisher_property_section_id":"FILTER_PUBLISHER_PROPERTY_SECTION_ID", - "refund_reason":"FILTER_REFUND_REASON", - "region":"FILTER_REGION_NAME", - "region_id":"FILTER_REGION", - "rewarded":"FILTER_REWARDED", - "sensitive_category":"FILTER_SENSITIVE_CATEGORY", - "served_pixel_density":"FILTER_SERVED_PIXEL_DENSITY", - "time_of_day":"FILTER_TIME_OF_DAY", - "time_to_conversion":"FILTER_CONVERSION_DELAY", - "variant_id":"FILTER_VARIANT_ID", - "variant_name":"FILTER_VARIANT_NAME", - "variant_version":"FILTER_VARIANT_VERSION", - "verification_video_player_size":"FILTER_VERIFICATION_VIDEO_PLAYER_SIZE", - "verification_video_position":"FILTER_VERIFICATION_VIDEO_POSITION", - "video_continuous_play":"FILTER_VIDEO_CONTINUOUS_PLAY", - "video_player_size":"FILTER_VIDEO_PLAYER_SIZE", - "video_skippable_support":"FILTER_SKIPPABLE_SUPPORT", - "week":"FILTER_WEEK", - "zip_code":"FILTER_ZIP_POSTAL_CODE", - "zip_code_id":"FILTER_ZIP_CODE", - "age":"FILTER_AGE", - "gender":"FILTER_GENDER", - "potential_impressions":"METRIC_POTENTIAL_IMPRESSIONS", - "unique_cookies_with_impressions":"METRIC_UNIQUE_COOKIES_WITH_IMPRESSIONS", - "cm_post_click_revenue":"METRIC_CM_POST_CLICK_REVENUE", - "cm_post_view_revenue":"METRIC_CM_POST_VIEW_REVENUE", - "cookie_consented_floodlight_impressions":"METRIC_COOKIE_CONSENTED_FLOODLIGHT_IMPRESSIONS", - "cookie_unconsented_floodlight_impressions":"METRIC_COOKIE_UNCONSENTED_FLOODLIGHT_IMPRESSIONS", - "duplicate_floodlight_impressions":"METRIC_DUPLICATE_FLOODLIGHT_IMPRESSIONS", - "floodlight_impressions":"METRIC_FLOODLIGHT_IMPRESSIONS", - "post_click_conversions":"METRIC_LAST_CLICKS", - "post_view_conversions":"METRIC_LAST_IMPRESSIONS", - "total_conversions":"METRIC_TOTAL_CONVERSIONS", - "cookie_reach_average_impression_frequency":"METRIC_COOKIE_REACH_AVERAGE_IMPRESSION_FREQUENCY", - "cookie_reach_impression_reach":"METRIC_COOKIE_REACH_IMPRESSION_REACH", - "unique_reach_average_impression_frequency":"METRIC_UNIQUE_REACH_AVERAGE_IMPRESSION_FREQUENCY", - "unique_reach_click_reach":"METRIC_UNIQUE_REACH_CLICK_REACH", - "unique_reach_impression_reach":"METRIC_UNIQUE_REACH_IMPRESSION_REACH", - "unique_reach_total_reach":"METRIC_UNIQUE_REACH_TOTAL_REACH", - "pct_clicks_leading_to_conversions":"METRIC_CLICK_TO_POST_CLICK_CONVERSION_RATE", - "pct_impressions_leading_to_conversions":"METRIC_IMPRESSIONS_TO_CONVERSION_RATE", - "pct_impressions_with_positive_custom_value":"METRIC_PERCENT_IMPRESSIONS_WITH_POSITIVE_CUSTOM_VALUE", - "active_view_pct_audible_and_visible_at_completion":"METRIC_ACTIVE_VIEW_PERCENT_AUDIBLE_VISIBLE_ON_COMPLETE", - "active_view_pct_audible_and_visible_at_first_quartile":"METRIC_ACTIVE_VIEW_PERCENT_AUDIBLE_VISIBLE_FIRST_QUAR", - "active_view_pct_audible_and_visible_at_midpoint":"METRIC_ACTIVE_VIEW_PERCENT_AUDIBLE_VISIBLE_SECOND_QUAR", - "active_view_pct_audible_and_visible_at_start":"METRIC_ACTIVE_VIEW_PERCENT_AUDIBLE_VISIBLE_AT_START", - "active_view_pct_audible_and_visible_at_third_quartile":"METRIC_ACTIVE_VIEW_PERCENT_AUDIBLE_VISIBLE_THIRD_QUAR", - "active_view_pct_audible_impressions":"METRIC_ACTIVE_VIEW_PERCENT_AUDIBLE_IMPRESSIONS", - "active_view_pct_full_screen":"METRIC_ACTIVE_VIEW_PERCENT_FULL_SCREEN", - "active_view_pct_fully_on_screen_2_sec":"METRIC_ACTIVE_VIEW_PERCENT_FULLY_ON_SCREEN_2_SEC", - "active_view_pct_in_background":"METRIC_ACTIVE_VIEW_PERCENT_IN_BACKGROUND", - "active_view_pct_measurable_impressions":"METRIC_ACTIVE_VIEW_PCT_MEASURABLE_IMPRESSIONS", - "active_view_pct_of_ad_played":"METRIC_ACTIVE_VIEW_PERCENT_OF_AD_PLAYED", - "active_view_pct_of_completed_impressions_audible_and_visible":"METRIC_ACTIVE_VIEW_PERCENT_OF_COMPLETED_IMPRESSIONS_AUDIBLE_AND_VISIBLE", - "active_view_pct_of_completed_impressions_visible":"METRIC_ACTIVE_VIEW_PERCENT_OF_COMPLETED_IMPRESSIONS_VISIBLE", - "active_view_pct_of_first_quartile_impressions_audible_and_visible":"METRIC_ACTIVE_VIEW_PERCENT_OF_FIRST_QUARTILE_IMPRESSIONS_AUDIBLE_AND_VISIBLE", - "active_view_pct_of_first_quartile_impressions_visible":"METRIC_ACTIVE_VIEW_PERCENT_OF_FIRST_QUARTILE_IMPRESSIONS_VISIBLE", - "active_view_pct_of_midpoint_impressions_audible_and_visible":"METRIC_ACTIVE_VIEW_PERCENT_OF_MIDPOINT_IMPRESSIONS_AUDIBLE_AND_VISIBLE", - "active_view_pct_of_midpoint_impressions_visible":"METRIC_ACTIVE_VIEW_PERCENT_OF_MIDPOINT_IMPRESSIONS_VISIBLE", - "active_view_pct_of_third_quartile_impressions_audible_and_visible":"METRIC_ACTIVE_VIEW_PERCENT_OF_THIRD_QUARTILE_IMPRESSIONS_AUDIBLE_AND_VISIBLE", - "active_view_pct_of_third_quartile_impressions_visible":"METRIC_ACTIVE_VIEW_PERCENT_OF_THIRD_QUARTILE_IMPRESSIONS_VISIBLE", - "active_view_pct_play_time_audible":"METRIC_ACTIVE_VIEW_PERCENT_PLAY_TIME_AUDIBLE", - "active_view_pct_play_time_audible_and_visible":"METRIC_ACTIVE_VIEW_PERCENT_PLAY_TIME_AUDIBLE_AND_VISIBLE", - "active_view_pct_play_time_visible":"METRIC_ACTIVE_VIEW_PERCENT_PLAY_TIME_VISIBLE", - "active_view_pct_viewable_impressions":"METRIC_ACTIVE_VIEW_PCT_VIEWABLE_IMPRESSIONS", - "active_view_pct_visible_10_seconds":"METRIC_ACTIVE_VIEW_PERCENT_VIEWABLE_FOR_TIME_THRESHOLD", - "active_view_pct_visible_at_completion":"METRIC_ACTIVE_VIEW_PERCENT_VISIBLE_ON_COMPLETE", - "active_view_pct_visible_at_first_quartile":"METRIC_ACTIVE_VIEW_PERCENT_VISIBLE_FIRST_QUAR", - "active_view_pct_visible_at_midpoint":"METRIC_ACTIVE_VIEW_PERCENT_VISIBLE_SECOND_QUAR", - "active_view_pct_visible_at_start":"METRIC_ACTIVE_VIEW_PERCENT_VISIBLE_AT_START", - "active_view_pct_visible_at_third_quartile":"METRIC_ACTIVE_VIEW_PERCENT_VISIBLE_THIRD_QUAR", - "active_view_audible_and_fully_on_screen_for_half_of_duration_15_sec_cap_impressions":"METRIC_ACTIVE_VIEW_AUDIBLE_FULLY_ON_SCREEN_HALF_OF_DURATION_IMPRESSIONS", - "active_view_audible_and_fully_on_screen_for_half_of_duration_15_sec_cap_measurable_impressions":"METRIC_ACTIVE_VIEW_AUDIBLE_FULLY_ON_SCREEN_HALF_OF_DURATION_MEASURABLE_IMPRESSIONS", - "active_view_audible_and_fully_on_screen_for_half_of_duration_15_sec_cap_rate":"METRIC_ACTIVE_VIEW_AUDIBLE_FULLY_ON_SCREEN_HALF_OF_DURATION_RATE", - "active_view_audible_and_fully_on_screen_for_half_of_duration_trueview_impressions":"METRIC_ACTIVE_VIEW_AUDIBLE_FULLY_ON_SCREEN_HALF_OF_DURATION_TRUEVIEW_IMPRESSIONS", - "active_view_audible_and_fully_on_screen_for_half_of_duration_trueview_measurable_impressions":"METRIC_ACTIVE_VIEW_AUDIBLE_FULLY_ON_SCREEN_HALF_OF_DURATION_TRUEVIEW_MEASURABLE_IMPRESSIONS", - "active_view_audible_and_fully_on_screen_for_half_of_duration_trueview_rate":"METRIC_ACTIVE_VIEW_AUDIBLE_FULLY_ON_SCREEN_HALF_OF_DURATION_TRUEVIEW_RATE", - "active_view_average_viewable_time_seconds":"METRIC_ACTIVE_VIEW_AVERAGE_VIEWABLE_TIME", - "active_view_custom_metric_measurable_impressions":"METRIC_ACTIVE_VIEW_CUSTOM_METRIC_MEASURABLE_IMPRESSIONS", - "active_view_custom_metric_viewable_impressions":"METRIC_ACTIVE_VIEW_CUSTOM_METRIC_VIEWABLE_IMPRESSIONS", - "active_view_custom_metric_viewable_rate":"METRIC_ACTIVE_VIEW_CUSTOM_METRIC_VIEWABLE_RATE", - "active_view_eligible_impressions":"METRIC_ACTIVE_VIEW_ELIGIBLE_IMPRESSIONS", - "active_view_impression_distribution_not_measurable":"METRIC_ACTIVE_VIEW_DISTRIBUTION_UNMEASURABLE", - "active_view_impression_distribution_not_viewable":"METRIC_ACTIVE_VIEW_DISTRIBUTION_UNVIEWABLE", - "active_view_impression_distribution_viewable":"METRIC_ACTIVE_VIEW_DISTRIBUTION_VIEWABLE", - "active_view_impressions_audible_and_visible_at_completion":"METRIC_ACTIVE_VIEW_AUDIBLE_VISIBLE_ON_COMPLETE_IMPRESSIONS", - "active_view_impressions_visible_10_seconds":"METRIC_ACTIVE_VIEW_VIEWABLE_FOR_TIME_THRESHOLD", - "active_view_measurable_impressions":"METRIC_ACTIVE_VIEW_MEASURABLE_IMPRESSIONS", - "active_view_not_measurable_impressions":"METRIC_ACTIVE_VIEW_UNMEASURABLE_IMPRESSIONS", - "active_view_not_viewable_impressions":"METRIC_ACTIVE_VIEW_UNVIEWABLE_IMPRESSIONS", - "active_view_viewable_impressions":"METRIC_ACTIVE_VIEW_VIEWABLE_IMPRESSIONS", - "adlingo_fee_advertiser_currency":"METRIC_ADLINGO_FEE_ADVERTISER_CURRENCY", - "adloox_fee_advertiser_currency":"METRIC_FEE21_ADVERTISER", - "adloox_fee_partner_currency":"METRIC_FEE21_PARTNER", - "adloox_fee_usd":"METRIC_FEE21_USD", - "adloox_pre_bid_fee_advertiser_currency":"METRIC_FEE22_ADVERTISER", - "adloox_pre_bid_fee_partner_currency":"METRIC_FEE22_PARTNER", - "adloox_pre_bid_fee_usd":"METRIC_FEE22_USD", - "adsafe_fee_advertiser_currency":"METRIC_FEE4_ADVERTISER", - "adsafe_fee_partner_currency":"METRIC_FEE4_PARTNER", - "adsafe_fee_usd":"METRIC_FEE4_USD", - "adxpose_fee_advertiser_currency":"METRIC_FEE5_ADVERTISER", - "adxpose_fee_partner_currency":"METRIC_FEE5_PARTNER", - "adxpose_fee_usd":"METRIC_FEE5_USD", - "agency_trading_desk_fee_advertiser_currency":"METRIC_FEE10_ADVERTISER", - "agency_trading_desk_fee_partner_currency":"METRIC_FEE10_PARTNER", - "agency_trading_desk_fee_usd":"METRIC_FEE10_USD", - "aggregate_knowledge_fee_advertiser_currency":"METRIC_FEE7_ADVERTISER", - "aggregate_knowledge_fee_partner_currency":"METRIC_FEE7_PARTNER", - "aggregate_knowledge_fee_usd":"METRIC_FEE7_USD", - "audio_client_cost_ecpcl_advertiser_currency":"METRIC_AUDIO_CLIENT_COST_ECPCL_ADVERTISER_CURRENCY", - "audio_media_cost_ecpcl_advertiser_currency":"METRIC_AUDIO_MEDIA_COST_ECPCL_ADVERTISER_CURRENCY", - "audio_mutes_audio":"METRIC_AUDIO_MUTES_AUDIO", - "audio_mutes_video":"METRIC_RICH_MEDIA_VIDEO_MUTES", - "audio_revenue_ecpcl_advertiser_currency":"METRIC_AUDIO_REVENUE_ECPCL_ADVERTISER_CURRENCY", - "audio_unmutes_audio":"METRIC_AUDIO_UNMUTES_AUDIO", - "audio_unmutes_video":"METRIC_AUDIO_UNMUTES_VIDEO", - "average_display_time":"METRIC_AVERAGE_DISPLAY_TIME", - "average_interaction_time":"METRIC_AVERAGE_INTERACTION_TIME", - "begin_to_render_eligible_impressions":"METRIC_BEGIN_TO_RENDER_ELIGIBLE_IMPRESSIONS", - "begin_to_render_impressions":"METRIC_BEGIN_TO_RENDER_IMPRESSIONS", - "billable_cost_advertiser_currency":"METRIC_BILLABLE_COST_ADVERTISER", - "billable_cost_partner_currency":"METRIC_BILLABLE_COST_PARTNER", - "billable_cost_usd":"METRIC_BILLABLE_COST_USD", - "billable_impressions":"METRIC_BILLABLE_IMPRESSIONS", - "click_rate_ctr":"METRIC_CTR", - "clicks":"METRIC_CLICKS", - "client_cost_advertiser_currency":"METRIC_CLIENT_COST_ADVERTISER_CURRENCY", - "client_cost_ecpa_advertiser_currency":"METRIC_CLIENT_COST_ECPA_ADVERTISER_CURRENCY", - "client_cost_ecpa_pc_advertiser_currency":"METRIC_CLIENT_COST_ECPA_PC_ADVERTISER_CURRENCY", - "client_cost_ecpa_pv_advertiser_currency":"METRIC_CLIENT_COST_ECPA_PV_ADVERTISER_CURRENCY", - "client_cost_ecpc_advertiser_currency":"METRIC_CLIENT_COST_ECPC_ADVERTISER_CURRENCY", - "client_cost_ecpm_advertiser_currency":"METRIC_CLIENT_COST_ECPM_ADVERTISER_CURRENCY", - "client_cost_viewable_ecpm_advertiser_currency":"METRIC_CLIENT_COST_VIEWABLE_ECPM_ADVERTISER_CURRENCY", - "cm_post_click_revenue__cross_environment":"METRIC_CM_POST_CLICK_REVENUE_CROSS_ENVIRONMENT", - "cm_post_view_revenue__cross_environment":"METRIC_CM_POST_VIEW_REVENUE_CROSS_ENVIRONMENT", - "companion_clicks_audio":"METRIC_COMPANION_CLICKS_AUDIO", - "companion_clicks_video":"METRIC_VIDEO_COMPANION_CLICKS", - "companion_impressions_audio":"METRIC_COMPANION_IMPRESSIONS_AUDIO", - "companion_impressions_video":"METRIC_VIDEO_COMPANION_IMPRESSIONS", - "complete_listens_audio":"METRIC_COMPLETE_LISTENS_AUDIO", - "complete_views_video":"METRIC_RICH_MEDIA_VIDEO_COMPLETIONS", - "completion_rate_audio":"METRIC_COMPLETION_RATE_AUDIO", - "completion_rate_video":"METRIC_VIDEO_COMPLETION_RATE", - "comscore_vce_in_doubleclick_fee_advertiser_currency":"METRIC_FEE20_ADVERTISER", - "comscore_vce_in_doubleclick_fee_partner_currency":"METRIC_FEE20_PARTNER", - "comscore_vce_in_doubleclick_fee_usd":"METRIC_FEE20_USD", - "conversions_per_1000_impressions":"METRIC_CONVERSIONS_PER_MILLE", - "cookie_unconsented_clicks":"METRIC_TRACKING_UNCONSENTED_CLICKS", - "counters":"METRIC_COUNTERS", - "cpm_fee_1_advertiser_currency":"METRIC_CPM_FEE1_ADVERTISER", - "cpm_fee_1_partner_currency":"METRIC_CPM_FEE1_PARTNER", - "cpm_fee_1_usd":"METRIC_CPM_FEE1_USD", - "cpm_fee_2_advertiser_currency":"METRIC_CPM_FEE2_ADVERTISER", - "cpm_fee_2_partner_currency":"METRIC_CPM_FEE2_PARTNER", - "cpm_fee_2_usd":"METRIC_CPM_FEE2_USD", - "cpm_fee_3_advertiser_currency":"METRIC_CPM_FEE3_ADVERTISER", - "cpm_fee_3_partner_currency":"METRIC_CPM_FEE3_PARTNER", - "cpm_fee_3_usd":"METRIC_CPM_FEE3_USD", - "cpm_fee_4_advertiser_currency":"METRIC_CPM_FEE4_ADVERTISER", - "cpm_fee_4_partner_currency":"METRIC_CPM_FEE4_PARTNER", - "cpm_fee_4_usd":"METRIC_CPM_FEE4_USD", - "cpm_fee_5_advertiser_currency":"METRIC_CPM_FEE5_ADVERTISER", - "cpm_fee_5_partner_currency":"METRIC_CPM_FEE5_PARTNER", - "cpm_fee_5_usd":"METRIC_CPM_FEE5_USD", - "custom_fee_1_advertiser_currency":"METRIC_CUSTOM_FEE_1_ADVERTISER_CURRENCY", - "custom_fee_2_advertiser_currency":"METRIC_CUSTOM_FEE_2_ADVERTISER_CURRENCY", - "custom_fee_3_advertiser_currency":"METRIC_CUSTOM_FEE_3_ADVERTISER_CURRENCY", - "custom_fee_4_advertiser_currency":"METRIC_CUSTOM_FEE_4_ADVERTISER_CURRENCY", - "custom_fee_5_advertiser_currency":"METRIC_CUSTOM_FEE_5_ADVERTISER_CURRENCY", - "data_fees_advertiser_currency":"METRIC_DATA_COST_ADVERTISER", - "data_fees_partner_currency":"METRIC_DATA_COST_PARTNER", - "data_fees_usd":"METRIC_DATA_COST_USD", - "data_management_platform_fee_advertiser_currency":"METRIC_FEE11_ADVERTISER", - "data_management_platform_fee_partner_currency":"METRIC_FEE11_PARTNER", - "data_management_platform_fee_usd":"METRIC_FEE11_USD", - "doubleverify_fee_advertiser_currency":"METRIC_FEE3_ADVERTISER", - "doubleverify_fee_partner_currency":"METRIC_FEE3_PARTNER", - "doubleverify_fee_usd":"METRIC_FEE3_USD", - "doubleverify_pre_bid_fee_advertiser_currency":"METRIC_FEE13_ADVERTISER", - "doubleverify_pre_bid_fee_partner_currency":"METRIC_FEE13_PARTNER", - "doubleverify_pre_bid_fee_usd":"METRIC_FEE13_USD", - "engagement_rate":"METRIC_DBM_ENGAGEMENT_RATE", - "engagements":"METRIC_ENGAGEMENTS", - "estimated_cpm_for_impressions_with_custom_value_advertiser_currency":"METRIC_ESTIMATED_CPM_FOR_IMPRESSIONS_WITH_CUSTOM_VALUE_ADVERTISER_CURRENCY", - "estimated_total_cost_for_impressions_with_custom_value_advertiser_currency":"METRIC_ESTIMATED_TOTAL_COST_FOR_IMPRESSIONS_WITH_CUSTOM_VALUE_ADVERTISER_CURRENCY", - "evidon_fee_advertiser_currency":"METRIC_FEE9_ADVERTISER", - "evidon_fee_partner_currency":"METRIC_FEE9_PARTNER", - "evidon_fee_usd":"METRIC_FEE9_USD", - "exits":"METRIC_EXITS", - "expansions":"METRIC_EXPANSIONS", - "first_quartile_audio":"METRIC_FIRST_QUARTILE_AUDIO", - "first_quartile_views_video":"METRIC_RICH_MEDIA_VIDEO_FIRST_QUARTILE_COMPLETES", - "fullscreens_video":"METRIC_RICH_MEDIA_VIDEO_FULL_SCREENS", - "general_invalid_traffic_givt_active_view_eligible_impressions":"METRIC_GIVT_ACTIVE_VIEW_ELIGIBLE_IMPRESSIONS", - "general_invalid_traffic_givt_active_view_measurable_impressions":"METRIC_GIVT_ACTIVE_VIEW_MEASURABLE_IMPRESSIONS", - "general_invalid_traffic_givt_active_view_viewable_impressions":"METRIC_GIVT_ACTIVE_VIEW_VIEWABLE_IMPRESSIONS", - "general_invalid_traffic_givt_begin_to_render_impressions":"METRIC_GIVT_BEGIN_TO_RENDER_IMPRESSIONS", - "general_invalid_traffic_givt_clicks":"METRIC_GIVT_CLICKS", - "general_invalid_traffic_givt_impressions":"METRIC_GENERAL_INVALID_TRAFFIC_GIVT_IMPRESSIONS", - "general_invalid_traffic_givt_tracked_ads":"METRIC_GENERAL_INVALID_TRAFFIC_GIVT_TRACKED_ADS", - "gmail_conversions":"METRIC_GMAIL_CONVERSIONS", - "gmail_post_click_conversions":"METRIC_GMAIL_POST_CLICK_CONVERSIONS", - "gmail_post_view_conversions":"METRIC_GMAIL_POST_VIEW_CONVERSIONS", - "impression_custom_value_cost":"METRIC_IMPRESSION_CUSTOM_VALUE_COST", - "impressions":"METRIC_IMPRESSIONS", - "impressions_with_custom_value":"METRIC_IMPRESSIONS_WITH_CUSTOM_VALUE", - "impressions_with_positive_custom_value":"METRIC_IMPRESSIONS_WITH_POSITIVE_CUSTOM_VALUE", - "integral_ad_science_pre_bid_fee_advertiser_currency":"METRIC_FEE12_ADVERTISER", - "integral_ad_science_pre_bid_fee_partner_currency":"METRIC_FEE12_PARTNER", - "integral_ad_science_pre_bid_fee_usd":"METRIC_FEE12_USD", - "integral_ad_science_video_fee_advertiser_currency":"METRIC_FEE17_ADVERTISER", - "integral_ad_science_video_fee_partner_currency":"METRIC_FEE17_PARTNER", - "integral_ad_science_video_fee_usd":"METRIC_FEE17_USD", - "interactive_impressions":"METRIC_INTERACTIVE_IMPRESSIONS", - "invalid_active_view_eligible_impressions":"METRIC_INVALID_ACTIVE_VIEW_ELIGIBLE_IMPRESSIONS", - "invalid_active_view_measurable_impressions":"METRIC_INVALID_ACTIVE_VIEW_MEASURABLE_IMPRESSIONS", - "invalid_active_view_viewable_impressions":"METRIC_INVALID_ACTIVE_VIEW_VIEWABLE_IMPRESSIONS", - "invalid_begin_to_render_impressions":"METRIC_INVALID_BEGIN_TO_RENDER_IMPRESSIONS", - "invalid_clicks":"METRIC_INVALID_CLICKS", - "invalid_impressions":"METRIC_INVALID_IMPRESSIONS", - "invalid_tracked_ads":"METRIC_INVALID_TRACKED_ADS", - "media_cost_advertiser_currency":"METRIC_MEDIA_COST_ADVERTISER", - "media_cost_partner_currency":"METRIC_MEDIA_COST_PARTNER", - "media_cost_usd":"METRIC_MEDIA_COST_USD", - "media_cost_ecpa_advertiser_currency":"METRIC_MEDIA_COST_ECPA_ADVERTISER", - "media_cost_ecpa_partner_currency":"METRIC_MEDIA_COST_ECPA_PARTNER", - "media_cost_ecpa_pc_advertiser_currency":"METRIC_MEDIA_COST_ECPAPC_ADVERTISER", - "media_cost_ecpa_pv_advertiser_currency":"METRIC_MEDIA_COST_ECPAPV_ADVERTISER", - "media_cost_ecpa_usd":"METRIC_MEDIA_COST_ECPA_USD", - "media_cost_ecpc_advertiser_currency":"METRIC_MEDIA_COST_ECPC_ADVERTISER", - "media_cost_ecpc_partner_currency":"METRIC_MEDIA_COST_ECPC_PARTNER", - "media_cost_ecpc_pc_partner_currency":"METRIC_MEDIA_COST_ECPAPC_PARTNER", - "media_cost_ecpc_pc_usd":"METRIC_MEDIA_COST_ECPAPC_USD", - "media_cost_ecpc_pv_partner_currency":"METRIC_MEDIA_COST_ECPAPV_PARTNER", - "media_cost_ecpc_pv_usd":"METRIC_MEDIA_COST_ECPAPV_USD", - "media_cost_ecpc_usd":"METRIC_MEDIA_COST_ECPC_USD", - "media_cost_ecpm_advertiser_currency":"METRIC_MEDIA_COST_ECPM_ADVERTISER", - "media_cost_ecpm_partner_currency":"METRIC_MEDIA_COST_ECPM_PARTNER", - "media_cost_ecpm_usd":"METRIC_MEDIA_COST_ECPM_USD", - "media_cost_viewable_ecpm_advertiser_currency":"METRIC_MEDIA_COST_VIEWABLE_ECPM_ADVERTISER", - "media_cost_viewable_ecpm_partner_currency":"METRIC_MEDIA_COST_VIEWABLE_ECPM_PARTNER", - "media_cost_viewable_ecpm_usd":"METRIC_MEDIA_COST_VIEWABLE_ECPM_USD", - "media_fee_1_advertiser_currency":"METRIC_MEDIA_FEE1_ADVERTISER", - "media_fee_1_partner_currency":"METRIC_MEDIA_FEE1_PARTNER", - "media_fee_1_usd":"METRIC_MEDIA_FEE1_USD", - "media_fee_2_advertiser_currency":"METRIC_MEDIA_FEE2_ADVERTISER", - "media_fee_2_partner_currency":"METRIC_MEDIA_FEE2_PARTNER", - "media_fee_2_usd":"METRIC_MEDIA_FEE2_USD", - "media_fee_3_advertiser_currency":"METRIC_MEDIA_FEE3_ADVERTISER", - "media_fee_3_partner_currency":"METRIC_MEDIA_FEE3_PARTNER", - "media_fee_3_usd":"METRIC_MEDIA_FEE3_USD", - "media_fee_4_advertiser_currency":"METRIC_MEDIA_FEE4_ADVERTISER", - "media_fee_4_partner_currency":"METRIC_MEDIA_FEE4_PARTNER", - "media_fee_4_usd":"METRIC_MEDIA_FEE4_USD", - "media_fee_5_advertiser_currency":"METRIC_MEDIA_FEE5_ADVERTISER", - "media_fee_5_partner_currency":"METRIC_MEDIA_FEE5_PARTNER", - "media_fee_5_usd":"METRIC_MEDIA_FEE5_USD", - "mediacost_data_fee_advertiser_currency":"METRIC_FEE16_ADVERTISER", - "mediacost_data_fee_partner_currency":"METRIC_FEE16_PARTNER", - "mediacost_data_fee_usd":"METRIC_FEE16_USD", - "midpoint_audio":"METRIC_MIDPOINT_AUDIO", - "midpoint_views_video":"METRIC_RICH_MEDIA_VIDEO_MIDPOINTS", - "moat_video_fee_advertiser_currency":"METRIC_FEE18_ADVERTISER", - "moat_video_fee_partner_currency":"METRIC_FEE18_PARTNER", - "moat_video_fee_usd":"METRIC_FEE18_USD", - "nielsen_digital_ad_ratings_fee_advertiser_currency":"METRIC_FEE19_ADVERTISER", - "nielsen_digital_ad_ratings_fee_partner_currency":"METRIC_FEE19_PARTNER", - "nielsen_digital_ad_ratings_fee_usd":"METRIC_FEE19_USD", - "pauses_audio":"METRIC_PAUSES_AUDIO", - "pauses_video":"METRIC_RICH_MEDIA_VIDEO_PAUSES", - "platform_fee_advertiser_currency":"METRIC_PLATFORM_FEE_ADVERTISER", - "platform_fee_partner_currency":"METRIC_PLATFORM_FEE_PARTNER", - "platform_fee_usd":"METRIC_PLATFORM_FEE_USD", - "platform_fee_rate":"METRIC_PLATFORM_FEE_RATE", - "post_view_conversions__cross_environment":"METRIC_POST_VIEW_CONVERSIONS_CROSS_ENVIRONMENT", - "premium_fee_advertiser_currency":"METRIC_PREMIUM_FEE_ADVERTISER_CURRENCY", - "profit_advertiser_currency":"METRIC_PROFIT_ADVERTISER", - "profit_partner_currency":"METRIC_PROFIT_PARTNER", - "profit_usd":"METRIC_PROFIT_USD", - "profit_ecpm_advertiser_currency":"METRIC_PROFIT_ECPM_ADVERTISER", - "profit_ecpm_partner_currency":"METRIC_PROFIT_ECPM_PARTNER", - "profit_ecpm_usd":"METRIC_PROFIT_ECPM_USD", - "profit_margin":"METRIC_PROFIT_MARGIN", - "profit_viewable_ecpm_advertiser_currency":"METRIC_PROFIT_VIEWABLE_ECPM_ADVERTISER", - "profit_viewable_ecpm_partner_currency":"METRIC_PROFIT_VIEWABLE_ECPM_PARTNER", - "profit_viewable_ecpm_usd":"METRIC_PROFIT_VIEWABLE_ECPM_USD", - "programmatic_guaranteed_impressions_passed_due_to_frequency":"METRIC_PROGRAMMATIC_GUARANTEED_IMPRESSIONS_PASSED_DUE_TO_FREQUENCY", - "programmatic_guaranteed_savings_re_invested_due_to_frequency_advertiser_currency":"METRIC_PROGRAMMATIC_GUARANTEED_SAVINGS_RE_INVESTED_DUE_TO_FREQUENCY_ADVERTISER_CURRENCY", - "refund_billable_cost_advertiser_currency":"METRIC_REFUND_BILLABLE_COST_ADVERTISER_CURRENCY", - "refund_media_cost_advertiser_currency":"METRIC_REFUND_MEDIA_COST_ADVERTISER_CURRENCY", - "refund_platform_fee_advertiser_currency":"METRIC_REFUND_PLATFORM_FEE_ADVERTISER_CURRENCY", - "revenue_advertiser_currency":"METRIC_REVENUE_ADVERTISER", - "revenue_partner_currency":"METRIC_REVENUE_PARTNER", - "revenue_usd":"METRIC_REVENUE_USD", - "revenue_ecpa_advertiser_currency":"METRIC_REVENUE_ECPA_ADVERTISER", - "revenue_ecpa_partner_currency":"METRIC_REVENUE_ECPA_PARTNER", - "revenue_ecpa_pc_advertiser_currency":"METRIC_REVENUE_ECPAPC_ADVERTISER", - "revenue_ecpa_pc_partner_currency":"METRIC_REVENUE_ECPAPC_PARTNER", - "revenue_ecpa_pc_usd":"METRIC_REVENUE_ECPAPC_USD", - "revenue_ecpa_pv_advertiser_currency":"METRIC_REVENUE_ECPAPV_ADVERTISER", - "revenue_ecpa_pv_partner_currency":"METRIC_REVENUE_ECPAPV_PARTNER", - "revenue_ecpa_pv_usd":"METRIC_REVENUE_ECPAPV_USD", - "revenue_ecpa_usd":"METRIC_REVENUE_ECPA_USD", - "revenue_ecpc_advertiser_currency":"METRIC_REVENUE_ECPC_ADVERTISER", - "revenue_ecpc_partner_currency":"METRIC_REVENUE_ECPC_PARTNER", - "revenue_ecpc_usd":"METRIC_REVENUE_ECPC_USD", - "revenue_ecpe_advertiser_currency":"METRIC_TRUEVIEW_AVERAGE_CPE_ADVERTISER", - "revenue_ecpe_partner_currency":"METRIC_TRUEVIEW_AVERAGE_CPE_PARTNER", - "revenue_ecpe_usd":"METRIC_TRUEVIEW_AVERAGE_CPE_USD", - "revenue_ecpm_advertiser_currency":"METRIC_REVENUE_ECPM_ADVERTISER", - "revenue_ecpm_partner_currency":"METRIC_REVENUE_ECPM_PARTNER", - "revenue_ecpm_usd":"METRIC_REVENUE_ECPM_USD", - "revenue_ecpv_advertiser_currency":"METRIC_TRUEVIEW_CPV_ADVERTISER", - "revenue_ecpv_partner_currency":"METRIC_TRUEVIEW_CPV_PARTNER", - "revenue_ecpv_usd":"METRIC_TRUEVIEW_CPV_USD", - "revenue_viewable_ecpm_advertiser_currency":"METRIC_REVENUE_VIEWABLE_ECPM_ADVERTISER", - "revenue_viewable_ecpm_partner_currency":"METRIC_REVENUE_VIEWABLE_ECPM_PARTNER", - "revenue_viewable_ecpm_usd":"METRIC_REVENUE_VIEWABLE_ECPM_USD", - "rich_media_engagements":"METRIC_RICH_MEDIA_ENGAGEMENTS", - "scrolls":"METRIC_RICH_MEDIA_SCROLLS", - "shoplocal_fee_advertiser_currency":"METRIC_FEE14_ADVERTISER", - "shoplocal_fee_partner_currency":"METRIC_FEE14_PARTNER", - "shoplocal_fee_usd":"METRIC_FEE14_USD", - "skips_video":"METRIC_RICH_MEDIA_VIDEO_SKIPS", - "starts_audio":"METRIC_STARTS_AUDIO", - "starts_video":"METRIC_RICH_MEDIA_VIDEO_PLAYS", - "stops_audio":"METRIC_STOPS_AUDIO", - "teracent_fee_advertiser_currency":"METRIC_FEE8_ADVERTISER", - "teracent_fee_partner_currency":"METRIC_FEE8_PARTNER", - "teracent_fee_usd":"METRIC_FEE8_USD", - "third_party_ad_server_fee_advertiser_currency":"METRIC_FEE2_ADVERTISER", - "third_party_ad_server_fee_partner_currency":"METRIC_FEE2_PARTNER", - "third_party_ad_server_fee_usd":"METRIC_FEE2_USD", - "third_quartile_audio":"METRIC_THIRD_QUARTILE_AUDIO", - "third_quartile_views_video":"METRIC_RICH_MEDIA_VIDEO_THIRD_QUARTILE_COMPLETES", - "timers":"METRIC_TIMERS", - "total_conversions__cross_environment":"METRIC_TOTAL_CONVERSIONS_CROSS_ENVIRONMENT", - "total_display_time":"METRIC_TOTAL_DISPLAY_TIME", - "total_impression_custom_value":"METRIC_TOTAL_IMPRESSION_CUSTOM_VALUE", - "total_interaction_time":"METRIC_TOTAL_INTERACTION_TIME", - "total_media_cost_advertiser_currency":"METRIC_TOTAL_MEDIA_COST_ADVERTISER", - "total_media_cost_partner_currency":"METRIC_TOTAL_MEDIA_COST_PARTNER", - "total_media_cost_usd":"METRIC_TOTAL_MEDIA_COST_USD", - "total_media_cost_ecpa_advertiser_currency":"METRIC_TOTAL_MEDIA_COST_ECPA_ADVERTISER", - "total_media_cost_ecpa_partner_currency":"METRIC_TOTAL_MEDIA_COST_ECPA_PARTNER", - "total_media_cost_ecpa_pc_advertiser_currency":"METRIC_TOTAL_MEDIA_COST_ECPAPC_ADVERTISER", - "total_media_cost_ecpa_pc_partner_currency":"METRIC_TOTAL_MEDIA_COST_ECPAPC_PARTNER", - "total_media_cost_ecpa_pc_usd":"METRIC_TOTAL_MEDIA_COST_ECPAPC_USD", - "total_media_cost_ecpa_pv_advertiser_currency":"METRIC_TOTAL_MEDIA_COST_ECPAPV_ADVERTISER", - "total_media_cost_ecpa_pv_partner_currency":"METRIC_TOTAL_MEDIA_COST_ECPAPV_PARTNER", - "total_media_cost_ecpa_pv_usd":"METRIC_TOTAL_MEDIA_COST_ECPAPV_USD", - "total_media_cost_ecpa_usd":"METRIC_TOTAL_MEDIA_COST_ECPA_USD", - "total_media_cost_ecpc_advertiser_currency":"METRIC_TOTAL_MEDIA_COST_ECPC_ADVERTISER", - "total_media_cost_ecpc_partner_currency":"METRIC_TOTAL_MEDIA_COST_ECPC_PARTNER", - "total_media_cost_ecpc_usd":"METRIC_TOTAL_MEDIA_COST_ECPC_USD", - "total_media_cost_ecpm_advertiser_currency":"METRIC_TOTAL_MEDIA_COST_ECPM_ADVERTISER", - "total_media_cost_ecpm_partner_currency":"METRIC_TOTAL_MEDIA_COST_ECPM_PARTNER", - "total_media_cost_ecpm_usd":"METRIC_TOTAL_MEDIA_COST_ECPM_USD", - "total_media_cost_viewable_ecpm_advertiser_currency":"METRIC_TOTAL_MEDIA_COST_VIEWABLE_ECPM_ADVERTISER", - "total_media_cost_viewable_ecpm_partner_currency":"METRIC_TOTAL_MEDIA_COST_VIEWABLE_ECPM_PARTNER", - "total_media_cost_viewable_ecpm_usd":"METRIC_TOTAL_MEDIA_COST_VIEWABLE_ECPM_USD", - "total_video_media_cost_ecpcv_advertiser_currency":"METRIC_TOTAL_MEDIA_COST_ECPCV_ADVERTISER", - "total_video_media_cost_ecpcv_partner_currency":"METRIC_TOTAL_MEDIA_COST_ECPCV_PARTNER", - "total_video_media_cost_ecpcv_usd":"METRIC_TOTAL_MEDIA_COST_ECPCV_USD", - "tracked_ads":"METRIC_TRACKED_ADS", - "trueview_general_invalid_traffic_givt_views":"METRIC_TRUEVIEW_GENERAL_INVALID_TRAFFIC_GIVT_VIEWS", - "trueview_invalid_views":"METRIC_TRUEVIEW_INVALID_VIEWS", - "trustmetrics_fee_advertiser_currency":"METRIC_FEE15_ADVERTISER", - "trustmetrics_fee_partner_currency":"METRIC_FEE15_PARTNER", - "trustmetrics_fee_usd":"METRIC_FEE15_USD", - "verifiable_impressions":"METRIC_VERIFIABLE_IMPRESSIONS", - "video_client_cost_ecpcv_advertiser_currency":"METRIC_VIDEO_CLIENT_COST_ECPCV_ADVERTISER_CURRENCY", - "video_media_cost_ecpcv_advertiser_currency":"METRIC_MEDIA_COST_ECPCV_ADVERTISER", - "video_media_cost_ecpcv_partner_currency":"METRIC_MEDIA_COST_ECPCV_PARTNER", - "video_media_cost_ecpcv_usd":"METRIC_MEDIA_COST_ECPCV_USD", - "vizu_fee_advertiser_currency":"METRIC_FEE6_ADVERTISER", - "vizu_fee_partner_currency":"METRIC_FEE6_PARTNER", - "vizu_fee_usd":"METRIC_FEE6_USD", - "youtube_view_rate":"METRIC_TRUEVIEW_VIEW_RATE", - "youtube_views":"METRIC_TRUEVIEW_VIEWS", - "pct_composition_impressions":"METRIC_DEMO_COMPOSITION_IMPRESSION", - "pct_composition_reach":"METRIC_VIRTUAL_PEOPLE_IMPRESSION_REACH_SHARE_PERCENT", - "pct_population_reach":"METRIC_VIRTUAL_PEOPLE_IMPRESSION_REACH_PERCENT", - "population":"METRIC_DEMO_POPULATION", - "target_rating_points":"METRIC_TARGET_RATING_POINTS", - "unique_reach_viewable_impression_reach":"METRIC_VIRTUAL_PEOPLE_VIEWABLE_IMPRESSION_REACH_BY_DEMO", - "viewable_target_rating_points":"METRIC_VIEWABLE_GROSS_RATING_POINTS", - "viewable_impressions":"METRIC_GRP_CORRECTED_VIEWABLE_IMPRESSIONS", - "pct_viewable_composition_impressions":"METRIC_GRP_CORRECTED_VIEWABLE_IMPRESSIONS_SHARE_PERCENT", - "pct_viewable_composition_reach":"METRIC_VIRTUAL_PEOPLE_VIEWABLE_IMPRESSION_REACH_SHARE_PERCENT", - "pct_viewable_population_reach":"METRIC_VIRTUAL_PEOPLE_VIEWABLE_IMPRESSION_REACH_PERCENT", -} \ No newline at end of file + "audience_list": "FILTER_AUDIENCE_LIST", + "date": "FILTER_DATE", + "eligible_cookies_on_first_party_audience_list": "FILTER_ELIGIBLE_COOKIES_ON_FIRST_PARTY_AUDIENCE_LIST", + "eligible_cookies_on_third_party_audience_list_and_interest": "FILTER_ELIGIBLE_COOKIES_ON_THIRD_PARTY_AUDIENCE_LIST_AND_INTEREST", + "first_party_audience_list": "FILTER_USER_LIST_FIRST_PARTY_NAME", + "first_party_audience_list_cost": "FILTER_FIRST_PARTY_AUDIENCE_LIST_COST", + "first_party_audience_list_id": "FILTER_USER_LIST_FIRST_PARTY", + "first_party_audience_list_type": "FILTER_FIRST_PARTY_AUDIENCE_LIST_TYPE", + "match_ratio": "FILTER_MATCH_RATIO", + "third_party_audience_list": "FILTER_USER_LIST_THIRD_PARTY_NAME", + "third_party_audience_list_cost": "FILTER_THIRD_PARTY_AUDIENCE_LIST_COST", + "third_party_audience_list_id": "FILTER_USER_LIST_THIRD_PARTY", + "third_party_audience_list_type": "FILTER_THIRD_PARTY_AUDIENCE_LIST_TYPE", + "advertiser": "FILTER_ADVERTISER_NAME", + "advertiser_currency": "FILTER_ADVERTISER_CURRENCY", + "advertiser_id": "FILTER_ADVERTISER", + "advertiser_integration_code": "FILTER_ADVERTISER_INTEGRATION_CODE", + "advertiser_status": "FILTER_ADVERTISER_INTEGRATION_STATUS", + "advertiser_time_zone": "FILTER_ADVERTISER_TIMEZONE", + "app_url": "FILTER_APP_URL", + "app_url_excluded": "FILTER_APP_URL_EXCLUDED", + "app_url_id": "FILTER_SITE_ID", + "campaign": "FILTER_MEDIA_PLAN_NAME", + "campaign_id": "FILTER_MEDIA_PLAN", + "category": "FILTER_PAGE_CATEGORY", + "cm_placement_id": "FILTER_CM_PLACEMENT_ID", + "creative": "FILTER_CREATIVE", + "creative_asset": "FILTER_CREATIVE_ASSET", + "creative_attributes": "FILTER_CREATIVE_ATTRIBUTE", + "creative_height": "FILTER_CREATIVE_HEIGHT", + "creative_id": "FILTER_CREATIVE_ID", + "creative_integration_code": "FILTER_CREATIVE_INTEGRATION_CODE", + "creative_rendered_in_amp": "FILTER_CREATIVE_RENDERED_IN_AMP", + "creative_size": "FILTER_CREATIVE_SIZE", + "creative_source": "FILTER_CREATIVE_SOURCE", + "creative_status": "FILTER_CREATIVE_STATUS", + "creative_type": "FILTER_CREATIVE_TYPE", + "creative_width": "FILTER_CREATIVE_WIDTH", + "day_of_week": "FILTER_DAY_OF_WEEK", + "exchange": "FILTER_EXCHANGE", + "exchange_code": "FILTER_EXCHANGE_CODE", + "exchange_id": "FILTER_EXCHANGE_ID", + "floodlight_activity": "FILTER_FLOODLIGHT_ACTIVITY", + "floodlight_activity_id": "FILTER_FLOODLIGHT_ACTIVITY_ID", + "insertion_order": "FILTER_INSERTION_ORDER_NAME", + "insertion_order_integration_code": "FILTER_INSERTION_ORDER_INTEGRATION_CODE", + "insertion_order_status": "FILTER_INSERTION_ORDER_STATUS", + "line_item": "FILTER_LINE_ITEM_NAME", + "line_item_id": "FILTER_LINE_ITEM", + "line_item_integration_code": "FILTER_LINE_ITEM_INTEGRATION_CODE", + "line_item_status": "FILTER_LINE_ITEM_STATUS", + "line_item_type": "FILTER_LINE_ITEM_TYPE", + "month": "FILTER_MONTH", + "order_id": "FILTER_ORDER_ID", + "partner": "FILTER_PARTNER_NAME", + "partner_currency": "FILTER_PARTNER_CURRENCY", + "partner_id": "FILTER_PARTNER", + "partner_status": "FILTER_PARTNER_STATUS", + "targeted_data_providers": "FILTER_TARGETED_DATA_PROVIDERS", + "year": "FILTER_YEAR", + "country": "FILTER_COUNTRY", + "country_id": "FILTER_COUNTRY_ID", + "insertion_order_id": "FILTER_INSERTION_ORDER", + "inventory_source": "FILTER_INVENTORY_SOURCE_NAME", + "active_view_custom_metric_id": "FILTER_ACTIVE_VIEW_CUSTOM_METRIC_ID", + "active_view_custom_metric_name": "FILTER_ACTIVE_VIEW_CUSTOM_METRIC_NAME", + "ad_position": "FILTER_AD_POSITION", + "ad_type": "FILTER_AD_TYPE", + "algorithm": "FILTER_ALGORITHM", + "algorithm_id": "FILTER_ALGORITHM_ID", + "amp_page_request": "FILTER_AMP_PAGE_REQUEST", + "attributed_userlist": "FILTER_ATTRIBUTED_USERLIST", + "attributed_userlist_cost": "FILTER_ATTRIBUTED_USERLIST_COST", + "attributed_userlist_id": "FILTER_TARGETED_USER_LIST", + "attributed_userlist_type": "FILTER_ATTRIBUTED_USERLIST_TYPE", + "attribution_model": "FILTER_ATTRIBUTION_MODEL", + "audience_list_cost": "FILTER_AUDIENCE_LIST_COST", + "audience_list_id": "FILTER_USER_LIST", + "audience_list_type": "FILTER_AUDIENCE_LIST_TYPE", + "audience_name": "FILTER_AUDIENCE_NAME", + "audience_type": "FILTER_AUDIENCE_TYPE", + "authorized_seller_state": "FILTER_AUTHORIZED_SELLER_STATE", + "billable_outcome": "FILTER_BILLABLE_OUTCOME", + "brand_lift_type": "FILTER_BRAND_LIFT_TYPE", + "browser_id": "FILTER_BROWSER", + "budget_segment_description": "FILTER_BUDGET_SEGMENT_DESCRIPTION", + "channel": "FILTER_CHANNEL_NAME", + "channel_id": "FILTER_CHANNEL_ID", + "channel_type": "FILTER_CHANNEL_TYPE", + "city": "FILTER_CITY_NAME", + "city_id": "FILTER_CITY", + "companion_creative": "FILTER_COMPANION_CREATIVE_NAME", + "companion_creative_id": "FILTER_COMPANION_CREATIVE_ID", + "companion_creative_size": "FILTER_COMPANION_CREATIVE_SIZE", + "data_provider": "FILTER_DATA_PROVIDER_NAME", + "data_provider_id": "FILTER_DATA_PROVIDER", + "detailed_demographics": "FILTER_DETAILED_DEMOGRAPHICS", + "detailed_demographics_id": "FILTER_DETAILED_DEMOGRAPHICS_ID", + "device": "FILTER_DEVICE", + "device_make": "FILTER_DEVICE_MAKE", + "device_model": "FILTER_DEVICE_MODEL", + "device_type": "FILTER_DEVICE_TYPE", + "digital_content_label": "FILTER_DIGITAL_CONTENT_LABEL", + "dma": "FILTER_DMA_NAME", + "dma_code": "FILTER_DMA", + "extension": "FILTER_EXTENSION", + "extension_status": "FILTER_EXTENSION_STATUS", + "extension_type": "FILTER_EXTENSION_TYPE", + "format": "FILTER_FORMAT", + "gmail_age": "FILTER_GMAIL_AGE", + "gmail_city": "FILTER_GMAIL_CITY", + "gmail_country": "FILTER_GMAIL_COUNTRY", + "gmail_device_type": "FILTER_GMAIL_DEVICE_TYPE", + "gmail_gender": "FILTER_GMAIL_GENDER", + "gmail_region": "FILTER_GMAIL_REGION", + "gmail_remarketing_list": "FILTER_GMAIL_REMARKETING_LIST", + "household_income": "FILTER_HOUSEHOLD_INCOME", + "impression_counting_method": "FILTER_IMPRESSION_COUNTING_METHOD", + "insertion_order_daily_frequency": "FILTER_CAMPAIGN_DAILY_FREQUENCY", + "interest": "FILTER_INTEREST", + "inventory_commitment_type": "FILTER_INVENTORY_COMMITMENT_TYPE", + "inventory_delivery_method": "FILTER_INVENTORY_DELIVERY_METHOD", + "inventory_rate_type": "FILTER_INVENTORY_RATE_TYPE", + "inventory_source_group": "FILTER_INVENTORY_SOURCE_GROUP", + "inventory_source_group_id": "FILTER_INVENTORY_SOURCE_GROUP_ID", + "inventory_source_id": "FILTER_INVENTORY_SOURCE_ID", + "inventory_source_id_external": "FILTER_INVENTORY_SOURCE_EXTERNAL_ID", + "inventory_source_type": "FILTER_INVENTORY_SOURCE_TYPE", + "isp_or_carrier": "FILTER_CARRIER_NAME", + "isp_or_carrier_id": "FILTER_CARRIER", + "keyword": "FILTER_KEYWORD", + "life_event": "FILTER_LIFE_EVENT", + "life_events": "FILTER_LIFE_EVENTS", + "line_item_daily_frequency": "FILTER_LINE_ITEM_DAILY_FREQUENCY", + "line_item_lifetime_frequency": "FILTER_LINE_ITEM_LIFETIME_FREQUENCY", + "max_video_duration": "FILTER_VIDEO_DURATION_SECONDS", + "measurement_source": "FILTER_MEASUREMENT_SOURCE", + "operating_system": "FILTER_OS", + "platform": "FILTER_PLATFORM", + "playback_method": "FILTER_PLAYBACK_METHOD", + "position_in_content": "FILTER_POSITION_IN_CONTENT", + "public_inventory": "FILTER_PUBLIC_INVENTORY", + "publisher_property": "FILTER_PUBLISHER_PROPERTY", + "publisher_property_id": "FILTER_PUBLISHER_PROPERTY_ID", + "publisher_property_section": "FILTER_PUBLISHER_PROPERTY_SECTION", + "publisher_property_section_id": "FILTER_PUBLISHER_PROPERTY_SECTION_ID", + "refund_reason": "FILTER_REFUND_REASON", + "region": "FILTER_REGION_NAME", + "region_id": "FILTER_REGION", + "rewarded": "FILTER_REWARDED", + "sensitive_category": "FILTER_SENSITIVE_CATEGORY", + "served_pixel_density": "FILTER_SERVED_PIXEL_DENSITY", + "time_of_day": "FILTER_TIME_OF_DAY", + "time_to_conversion": "FILTER_CONVERSION_DELAY", + "variant_id": "FILTER_VARIANT_ID", + "variant_name": "FILTER_VARIANT_NAME", + "variant_version": "FILTER_VARIANT_VERSION", + "verification_video_player_size": "FILTER_VERIFICATION_VIDEO_PLAYER_SIZE", + "verification_video_position": "FILTER_VERIFICATION_VIDEO_POSITION", + "video_continuous_play": "FILTER_VIDEO_CONTINUOUS_PLAY", + "video_player_size": "FILTER_VIDEO_PLAYER_SIZE", + "video_skippable_support": "FILTER_SKIPPABLE_SUPPORT", + "week": "FILTER_WEEK", + "zip_code": "FILTER_ZIP_POSTAL_CODE", + "zip_code_id": "FILTER_ZIP_CODE", + "age": "FILTER_AGE", + "gender": "FILTER_GENDER", + "potential_impressions": "METRIC_POTENTIAL_IMPRESSIONS", + "unique_cookies_with_impressions": "METRIC_UNIQUE_COOKIES_WITH_IMPRESSIONS", + "cm_post_click_revenue": "METRIC_CM_POST_CLICK_REVENUE", + "cm_post_view_revenue": "METRIC_CM_POST_VIEW_REVENUE", + "cookie_consented_floodlight_impressions": "METRIC_COOKIE_CONSENTED_FLOODLIGHT_IMPRESSIONS", + "cookie_unconsented_floodlight_impressions": "METRIC_COOKIE_UNCONSENTED_FLOODLIGHT_IMPRESSIONS", + "duplicate_floodlight_impressions": "METRIC_DUPLICATE_FLOODLIGHT_IMPRESSIONS", + "floodlight_impressions": "METRIC_FLOODLIGHT_IMPRESSIONS", + "post_click_conversions": "METRIC_LAST_CLICKS", + "post_view_conversions": "METRIC_LAST_IMPRESSIONS", + "total_conversions": "METRIC_TOTAL_CONVERSIONS", + "cookie_reach_average_impression_frequency": "METRIC_COOKIE_REACH_AVERAGE_IMPRESSION_FREQUENCY", + "cookie_reach_impression_reach": "METRIC_COOKIE_REACH_IMPRESSION_REACH", + "unique_reach_average_impression_frequency": "METRIC_UNIQUE_REACH_AVERAGE_IMPRESSION_FREQUENCY", + "unique_reach_click_reach": "METRIC_UNIQUE_REACH_CLICK_REACH", + "unique_reach_impression_reach": "METRIC_UNIQUE_REACH_IMPRESSION_REACH", + "unique_reach_total_reach": "METRIC_UNIQUE_REACH_TOTAL_REACH", + "pct_clicks_leading_to_conversions": "METRIC_CLICK_TO_POST_CLICK_CONVERSION_RATE", + "pct_impressions_leading_to_conversions": "METRIC_IMPRESSIONS_TO_CONVERSION_RATE", + "pct_impressions_with_positive_custom_value": "METRIC_PERCENT_IMPRESSIONS_WITH_POSITIVE_CUSTOM_VALUE", + "active_view_pct_audible_and_visible_at_completion": "METRIC_ACTIVE_VIEW_PERCENT_AUDIBLE_VISIBLE_ON_COMPLETE", + "active_view_pct_audible_and_visible_at_first_quartile": "METRIC_ACTIVE_VIEW_PERCENT_AUDIBLE_VISIBLE_FIRST_QUAR", + "active_view_pct_audible_and_visible_at_midpoint": "METRIC_ACTIVE_VIEW_PERCENT_AUDIBLE_VISIBLE_SECOND_QUAR", + "active_view_pct_audible_and_visible_at_start": "METRIC_ACTIVE_VIEW_PERCENT_AUDIBLE_VISIBLE_AT_START", + "active_view_pct_audible_and_visible_at_third_quartile": "METRIC_ACTIVE_VIEW_PERCENT_AUDIBLE_VISIBLE_THIRD_QUAR", + "active_view_pct_audible_impressions": "METRIC_ACTIVE_VIEW_PERCENT_AUDIBLE_IMPRESSIONS", + "active_view_pct_full_screen": "METRIC_ACTIVE_VIEW_PERCENT_FULL_SCREEN", + "active_view_pct_fully_on_screen_2_sec": "METRIC_ACTIVE_VIEW_PERCENT_FULLY_ON_SCREEN_2_SEC", + "active_view_pct_in_background": "METRIC_ACTIVE_VIEW_PERCENT_IN_BACKGROUND", + "active_view_pct_measurable_impressions": "METRIC_ACTIVE_VIEW_PCT_MEASURABLE_IMPRESSIONS", + "active_view_pct_of_ad_played": "METRIC_ACTIVE_VIEW_PERCENT_OF_AD_PLAYED", + "active_view_pct_of_completed_impressions_audible_and_visible": "METRIC_ACTIVE_VIEW_PERCENT_OF_COMPLETED_IMPRESSIONS_AUDIBLE_AND_VISIBLE", + "active_view_pct_of_completed_impressions_visible": "METRIC_ACTIVE_VIEW_PERCENT_OF_COMPLETED_IMPRESSIONS_VISIBLE", + "active_view_pct_of_first_quartile_impressions_audible_and_visible": "METRIC_ACTIVE_VIEW_PERCENT_OF_FIRST_QUARTILE_IMPRESSIONS_AUDIBLE_AND_VISIBLE", + "active_view_pct_of_first_quartile_impressions_visible": "METRIC_ACTIVE_VIEW_PERCENT_OF_FIRST_QUARTILE_IMPRESSIONS_VISIBLE", + "active_view_pct_of_midpoint_impressions_audible_and_visible": "METRIC_ACTIVE_VIEW_PERCENT_OF_MIDPOINT_IMPRESSIONS_AUDIBLE_AND_VISIBLE", + "active_view_pct_of_midpoint_impressions_visible": "METRIC_ACTIVE_VIEW_PERCENT_OF_MIDPOINT_IMPRESSIONS_VISIBLE", + "active_view_pct_of_third_quartile_impressions_audible_and_visible": "METRIC_ACTIVE_VIEW_PERCENT_OF_THIRD_QUARTILE_IMPRESSIONS_AUDIBLE_AND_VISIBLE", + "active_view_pct_of_third_quartile_impressions_visible": "METRIC_ACTIVE_VIEW_PERCENT_OF_THIRD_QUARTILE_IMPRESSIONS_VISIBLE", + "active_view_pct_play_time_audible": "METRIC_ACTIVE_VIEW_PERCENT_PLAY_TIME_AUDIBLE", + "active_view_pct_play_time_audible_and_visible": "METRIC_ACTIVE_VIEW_PERCENT_PLAY_TIME_AUDIBLE_AND_VISIBLE", + "active_view_pct_play_time_visible": "METRIC_ACTIVE_VIEW_PERCENT_PLAY_TIME_VISIBLE", + "active_view_pct_viewable_impressions": "METRIC_ACTIVE_VIEW_PCT_VIEWABLE_IMPRESSIONS", + "active_view_pct_visible_10_seconds": "METRIC_ACTIVE_VIEW_PERCENT_VIEWABLE_FOR_TIME_THRESHOLD", + "active_view_pct_visible_at_completion": "METRIC_ACTIVE_VIEW_PERCENT_VISIBLE_ON_COMPLETE", + "active_view_pct_visible_at_first_quartile": "METRIC_ACTIVE_VIEW_PERCENT_VISIBLE_FIRST_QUAR", + "active_view_pct_visible_at_midpoint": "METRIC_ACTIVE_VIEW_PERCENT_VISIBLE_SECOND_QUAR", + "active_view_pct_visible_at_start": "METRIC_ACTIVE_VIEW_PERCENT_VISIBLE_AT_START", + "active_view_pct_visible_at_third_quartile": "METRIC_ACTIVE_VIEW_PERCENT_VISIBLE_THIRD_QUAR", + "active_view_audible_and_fully_on_screen_for_half_of_duration_15_sec_cap_impressions": "METRIC_ACTIVE_VIEW_AUDIBLE_FULLY_ON_SCREEN_HALF_OF_DURATION_IMPRESSIONS", + "active_view_audible_and_fully_on_screen_for_half_of_duration_15_sec_cap_measurable_impressions": "METRIC_ACTIVE_VIEW_AUDIBLE_FULLY_ON_SCREEN_HALF_OF_DURATION_MEASURABLE_IMPRESSIONS", + "active_view_audible_and_fully_on_screen_for_half_of_duration_15_sec_cap_rate": "METRIC_ACTIVE_VIEW_AUDIBLE_FULLY_ON_SCREEN_HALF_OF_DURATION_RATE", + "active_view_audible_and_fully_on_screen_for_half_of_duration_trueview_impressions": "METRIC_ACTIVE_VIEW_AUDIBLE_FULLY_ON_SCREEN_HALF_OF_DURATION_TRUEVIEW_IMPRESSIONS", + "active_view_audible_and_fully_on_screen_for_half_of_duration_trueview_measurable_impressions": "METRIC_ACTIVE_VIEW_AUDIBLE_FULLY_ON_SCREEN_HALF_OF_DURATION_TRUEVIEW_MEASURABLE_IMPRESSIONS", + "active_view_audible_and_fully_on_screen_for_half_of_duration_trueview_rate": "METRIC_ACTIVE_VIEW_AUDIBLE_FULLY_ON_SCREEN_HALF_OF_DURATION_TRUEVIEW_RATE", + "active_view_average_viewable_time_seconds": "METRIC_ACTIVE_VIEW_AVERAGE_VIEWABLE_TIME", + "active_view_custom_metric_measurable_impressions": "METRIC_ACTIVE_VIEW_CUSTOM_METRIC_MEASURABLE_IMPRESSIONS", + "active_view_custom_metric_viewable_impressions": "METRIC_ACTIVE_VIEW_CUSTOM_METRIC_VIEWABLE_IMPRESSIONS", + "active_view_custom_metric_viewable_rate": "METRIC_ACTIVE_VIEW_CUSTOM_METRIC_VIEWABLE_RATE", + "active_view_eligible_impressions": "METRIC_ACTIVE_VIEW_ELIGIBLE_IMPRESSIONS", + "active_view_impression_distribution_not_measurable": "METRIC_ACTIVE_VIEW_DISTRIBUTION_UNMEASURABLE", + "active_view_impression_distribution_not_viewable": "METRIC_ACTIVE_VIEW_DISTRIBUTION_UNVIEWABLE", + "active_view_impression_distribution_viewable": "METRIC_ACTIVE_VIEW_DISTRIBUTION_VIEWABLE", + "active_view_impressions_audible_and_visible_at_completion": "METRIC_ACTIVE_VIEW_AUDIBLE_VISIBLE_ON_COMPLETE_IMPRESSIONS", + "active_view_impressions_visible_10_seconds": "METRIC_ACTIVE_VIEW_VIEWABLE_FOR_TIME_THRESHOLD", + "active_view_measurable_impressions": "METRIC_ACTIVE_VIEW_MEASURABLE_IMPRESSIONS", + "active_view_not_measurable_impressions": "METRIC_ACTIVE_VIEW_UNMEASURABLE_IMPRESSIONS", + "active_view_not_viewable_impressions": "METRIC_ACTIVE_VIEW_UNVIEWABLE_IMPRESSIONS", + "active_view_viewable_impressions": "METRIC_ACTIVE_VIEW_VIEWABLE_IMPRESSIONS", + "adlingo_fee_advertiser_currency": "METRIC_ADLINGO_FEE_ADVERTISER_CURRENCY", + "adloox_fee_advertiser_currency": "METRIC_FEE21_ADVERTISER", + "adloox_fee_partner_currency": "METRIC_FEE21_PARTNER", + "adloox_fee_usd": "METRIC_FEE21_USD", + "adloox_pre_bid_fee_advertiser_currency": "METRIC_FEE22_ADVERTISER", + "adloox_pre_bid_fee_partner_currency": "METRIC_FEE22_PARTNER", + "adloox_pre_bid_fee_usd": "METRIC_FEE22_USD", + "adsafe_fee_advertiser_currency": "METRIC_FEE4_ADVERTISER", + "adsafe_fee_partner_currency": "METRIC_FEE4_PARTNER", + "adsafe_fee_usd": "METRIC_FEE4_USD", + "adxpose_fee_advertiser_currency": "METRIC_FEE5_ADVERTISER", + "adxpose_fee_partner_currency": "METRIC_FEE5_PARTNER", + "adxpose_fee_usd": "METRIC_FEE5_USD", + "agency_trading_desk_fee_advertiser_currency": "METRIC_FEE10_ADVERTISER", + "agency_trading_desk_fee_partner_currency": "METRIC_FEE10_PARTNER", + "agency_trading_desk_fee_usd": "METRIC_FEE10_USD", + "aggregate_knowledge_fee_advertiser_currency": "METRIC_FEE7_ADVERTISER", + "aggregate_knowledge_fee_partner_currency": "METRIC_FEE7_PARTNER", + "aggregate_knowledge_fee_usd": "METRIC_FEE7_USD", + "audio_client_cost_ecpcl_advertiser_currency": "METRIC_AUDIO_CLIENT_COST_ECPCL_ADVERTISER_CURRENCY", + "audio_media_cost_ecpcl_advertiser_currency": "METRIC_AUDIO_MEDIA_COST_ECPCL_ADVERTISER_CURRENCY", + "audio_mutes_audio": "METRIC_AUDIO_MUTES_AUDIO", + "audio_mutes_video": "METRIC_RICH_MEDIA_VIDEO_MUTES", + "audio_revenue_ecpcl_advertiser_currency": "METRIC_AUDIO_REVENUE_ECPCL_ADVERTISER_CURRENCY", + "audio_unmutes_audio": "METRIC_AUDIO_UNMUTES_AUDIO", + "audio_unmutes_video": "METRIC_AUDIO_UNMUTES_VIDEO", + "average_display_time": "METRIC_AVERAGE_DISPLAY_TIME", + "average_interaction_time": "METRIC_AVERAGE_INTERACTION_TIME", + "begin_to_render_eligible_impressions": "METRIC_BEGIN_TO_RENDER_ELIGIBLE_IMPRESSIONS", + "begin_to_render_impressions": "METRIC_BEGIN_TO_RENDER_IMPRESSIONS", + "billable_cost_advertiser_currency": "METRIC_BILLABLE_COST_ADVERTISER", + "billable_cost_partner_currency": "METRIC_BILLABLE_COST_PARTNER", + "billable_cost_usd": "METRIC_BILLABLE_COST_USD", + "billable_impressions": "METRIC_BILLABLE_IMPRESSIONS", + "click_rate_ctr": "METRIC_CTR", + "clicks": "METRIC_CLICKS", + "client_cost_advertiser_currency": "METRIC_CLIENT_COST_ADVERTISER_CURRENCY", + "client_cost_ecpa_advertiser_currency": "METRIC_CLIENT_COST_ECPA_ADVERTISER_CURRENCY", + "client_cost_ecpa_pc_advertiser_currency": "METRIC_CLIENT_COST_ECPA_PC_ADVERTISER_CURRENCY", + "client_cost_ecpa_pv_advertiser_currency": "METRIC_CLIENT_COST_ECPA_PV_ADVERTISER_CURRENCY", + "client_cost_ecpc_advertiser_currency": "METRIC_CLIENT_COST_ECPC_ADVERTISER_CURRENCY", + "client_cost_ecpm_advertiser_currency": "METRIC_CLIENT_COST_ECPM_ADVERTISER_CURRENCY", + "client_cost_viewable_ecpm_advertiser_currency": "METRIC_CLIENT_COST_VIEWABLE_ECPM_ADVERTISER_CURRENCY", + "cm_post_click_revenue__cross_environment": "METRIC_CM_POST_CLICK_REVENUE_CROSS_ENVIRONMENT", + "cm_post_view_revenue__cross_environment": "METRIC_CM_POST_VIEW_REVENUE_CROSS_ENVIRONMENT", + "companion_clicks_audio": "METRIC_COMPANION_CLICKS_AUDIO", + "companion_clicks_video": "METRIC_VIDEO_COMPANION_CLICKS", + "companion_impressions_audio": "METRIC_COMPANION_IMPRESSIONS_AUDIO", + "companion_impressions_video": "METRIC_VIDEO_COMPANION_IMPRESSIONS", + "complete_listens_audio": "METRIC_COMPLETE_LISTENS_AUDIO", + "complete_views_video": "METRIC_RICH_MEDIA_VIDEO_COMPLETIONS", + "completion_rate_audio": "METRIC_COMPLETION_RATE_AUDIO", + "completion_rate_video": "METRIC_VIDEO_COMPLETION_RATE", + "comscore_vce_in_doubleclick_fee_advertiser_currency": "METRIC_FEE20_ADVERTISER", + "comscore_vce_in_doubleclick_fee_partner_currency": "METRIC_FEE20_PARTNER", + "comscore_vce_in_doubleclick_fee_usd": "METRIC_FEE20_USD", + "conversions_per_1000_impressions": "METRIC_CONVERSIONS_PER_MILLE", + "cookie_unconsented_clicks": "METRIC_TRACKING_UNCONSENTED_CLICKS", + "counters": "METRIC_COUNTERS", + "cpm_fee_1_advertiser_currency": "METRIC_CPM_FEE1_ADVERTISER", + "cpm_fee_1_partner_currency": "METRIC_CPM_FEE1_PARTNER", + "cpm_fee_1_usd": "METRIC_CPM_FEE1_USD", + "cpm_fee_2_advertiser_currency": "METRIC_CPM_FEE2_ADVERTISER", + "cpm_fee_2_partner_currency": "METRIC_CPM_FEE2_PARTNER", + "cpm_fee_2_usd": "METRIC_CPM_FEE2_USD", + "cpm_fee_3_advertiser_currency": "METRIC_CPM_FEE3_ADVERTISER", + "cpm_fee_3_partner_currency": "METRIC_CPM_FEE3_PARTNER", + "cpm_fee_3_usd": "METRIC_CPM_FEE3_USD", + "cpm_fee_4_advertiser_currency": "METRIC_CPM_FEE4_ADVERTISER", + "cpm_fee_4_partner_currency": "METRIC_CPM_FEE4_PARTNER", + "cpm_fee_4_usd": "METRIC_CPM_FEE4_USD", + "cpm_fee_5_advertiser_currency": "METRIC_CPM_FEE5_ADVERTISER", + "cpm_fee_5_partner_currency": "METRIC_CPM_FEE5_PARTNER", + "cpm_fee_5_usd": "METRIC_CPM_FEE5_USD", + "custom_fee_1_advertiser_currency": "METRIC_CUSTOM_FEE_1_ADVERTISER_CURRENCY", + "custom_fee_2_advertiser_currency": "METRIC_CUSTOM_FEE_2_ADVERTISER_CURRENCY", + "custom_fee_3_advertiser_currency": "METRIC_CUSTOM_FEE_3_ADVERTISER_CURRENCY", + "custom_fee_4_advertiser_currency": "METRIC_CUSTOM_FEE_4_ADVERTISER_CURRENCY", + "custom_fee_5_advertiser_currency": "METRIC_CUSTOM_FEE_5_ADVERTISER_CURRENCY", + "data_fees_advertiser_currency": "METRIC_DATA_COST_ADVERTISER", + "data_fees_partner_currency": "METRIC_DATA_COST_PARTNER", + "data_fees_usd": "METRIC_DATA_COST_USD", + "data_management_platform_fee_advertiser_currency": "METRIC_FEE11_ADVERTISER", + "data_management_platform_fee_partner_currency": "METRIC_FEE11_PARTNER", + "data_management_platform_fee_usd": "METRIC_FEE11_USD", + "doubleverify_fee_advertiser_currency": "METRIC_FEE3_ADVERTISER", + "doubleverify_fee_partner_currency": "METRIC_FEE3_PARTNER", + "doubleverify_fee_usd": "METRIC_FEE3_USD", + "doubleverify_pre_bid_fee_advertiser_currency": "METRIC_FEE13_ADVERTISER", + "doubleverify_pre_bid_fee_partner_currency": "METRIC_FEE13_PARTNER", + "doubleverify_pre_bid_fee_usd": "METRIC_FEE13_USD", + "engagement_rate": "METRIC_DBM_ENGAGEMENT_RATE", + "engagements": "METRIC_ENGAGEMENTS", + "estimated_cpm_for_impressions_with_custom_value_advertiser_currency": "METRIC_ESTIMATED_CPM_FOR_IMPRESSIONS_WITH_CUSTOM_VALUE_ADVERTISER_CURRENCY", + "estimated_total_cost_for_impressions_with_custom_value_advertiser_currency": "METRIC_ESTIMATED_TOTAL_COST_FOR_IMPRESSIONS_WITH_CUSTOM_VALUE_ADVERTISER_CURRENCY", + "evidon_fee_advertiser_currency": "METRIC_FEE9_ADVERTISER", + "evidon_fee_partner_currency": "METRIC_FEE9_PARTNER", + "evidon_fee_usd": "METRIC_FEE9_USD", + "exits": "METRIC_EXITS", + "expansions": "METRIC_EXPANSIONS", + "first_quartile_audio": "METRIC_FIRST_QUARTILE_AUDIO", + "first_quartile_views_video": "METRIC_RICH_MEDIA_VIDEO_FIRST_QUARTILE_COMPLETES", + "fullscreens_video": "METRIC_RICH_MEDIA_VIDEO_FULL_SCREENS", + "general_invalid_traffic_givt_active_view_eligible_impressions": "METRIC_GIVT_ACTIVE_VIEW_ELIGIBLE_IMPRESSIONS", + "general_invalid_traffic_givt_active_view_measurable_impressions": "METRIC_GIVT_ACTIVE_VIEW_MEASURABLE_IMPRESSIONS", + "general_invalid_traffic_givt_active_view_viewable_impressions": "METRIC_GIVT_ACTIVE_VIEW_VIEWABLE_IMPRESSIONS", + "general_invalid_traffic_givt_begin_to_render_impressions": "METRIC_GIVT_BEGIN_TO_RENDER_IMPRESSIONS", + "general_invalid_traffic_givt_clicks": "METRIC_GIVT_CLICKS", + "general_invalid_traffic_givt_impressions": "METRIC_GENERAL_INVALID_TRAFFIC_GIVT_IMPRESSIONS", + "general_invalid_traffic_givt_tracked_ads": "METRIC_GENERAL_INVALID_TRAFFIC_GIVT_TRACKED_ADS", + "gmail_conversions": "METRIC_GMAIL_CONVERSIONS", + "gmail_post_click_conversions": "METRIC_GMAIL_POST_CLICK_CONVERSIONS", + "gmail_post_view_conversions": "METRIC_GMAIL_POST_VIEW_CONVERSIONS", + "impression_custom_value_cost": "METRIC_IMPRESSION_CUSTOM_VALUE_COST", + "impressions": "METRIC_IMPRESSIONS", + "impressions_with_custom_value": "METRIC_IMPRESSIONS_WITH_CUSTOM_VALUE", + "impressions_with_positive_custom_value": "METRIC_IMPRESSIONS_WITH_POSITIVE_CUSTOM_VALUE", + "integral_ad_science_pre_bid_fee_advertiser_currency": "METRIC_FEE12_ADVERTISER", + "integral_ad_science_pre_bid_fee_partner_currency": "METRIC_FEE12_PARTNER", + "integral_ad_science_pre_bid_fee_usd": "METRIC_FEE12_USD", + "integral_ad_science_video_fee_advertiser_currency": "METRIC_FEE17_ADVERTISER", + "integral_ad_science_video_fee_partner_currency": "METRIC_FEE17_PARTNER", + "integral_ad_science_video_fee_usd": "METRIC_FEE17_USD", + "interactive_impressions": "METRIC_INTERACTIVE_IMPRESSIONS", + "invalid_active_view_eligible_impressions": "METRIC_INVALID_ACTIVE_VIEW_ELIGIBLE_IMPRESSIONS", + "invalid_active_view_measurable_impressions": "METRIC_INVALID_ACTIVE_VIEW_MEASURABLE_IMPRESSIONS", + "invalid_active_view_viewable_impressions": "METRIC_INVALID_ACTIVE_VIEW_VIEWABLE_IMPRESSIONS", + "invalid_begin_to_render_impressions": "METRIC_INVALID_BEGIN_TO_RENDER_IMPRESSIONS", + "invalid_clicks": "METRIC_INVALID_CLICKS", + "invalid_impressions": "METRIC_INVALID_IMPRESSIONS", + "invalid_tracked_ads": "METRIC_INVALID_TRACKED_ADS", + "media_cost_advertiser_currency": "METRIC_MEDIA_COST_ADVERTISER", + "media_cost_partner_currency": "METRIC_MEDIA_COST_PARTNER", + "media_cost_usd": "METRIC_MEDIA_COST_USD", + "media_cost_ecpa_advertiser_currency": "METRIC_MEDIA_COST_ECPA_ADVERTISER", + "media_cost_ecpa_partner_currency": "METRIC_MEDIA_COST_ECPA_PARTNER", + "media_cost_ecpa_pc_advertiser_currency": "METRIC_MEDIA_COST_ECPAPC_ADVERTISER", + "media_cost_ecpa_pv_advertiser_currency": "METRIC_MEDIA_COST_ECPAPV_ADVERTISER", + "media_cost_ecpa_usd": "METRIC_MEDIA_COST_ECPA_USD", + "media_cost_ecpc_advertiser_currency": "METRIC_MEDIA_COST_ECPC_ADVERTISER", + "media_cost_ecpc_partner_currency": "METRIC_MEDIA_COST_ECPC_PARTNER", + "media_cost_ecpc_pc_partner_currency": "METRIC_MEDIA_COST_ECPAPC_PARTNER", + "media_cost_ecpc_pc_usd": "METRIC_MEDIA_COST_ECPAPC_USD", + "media_cost_ecpc_pv_partner_currency": "METRIC_MEDIA_COST_ECPAPV_PARTNER", + "media_cost_ecpc_pv_usd": "METRIC_MEDIA_COST_ECPAPV_USD", + "media_cost_ecpc_usd": "METRIC_MEDIA_COST_ECPC_USD", + "media_cost_ecpm_advertiser_currency": "METRIC_MEDIA_COST_ECPM_ADVERTISER", + "media_cost_ecpm_partner_currency": "METRIC_MEDIA_COST_ECPM_PARTNER", + "media_cost_ecpm_usd": "METRIC_MEDIA_COST_ECPM_USD", + "media_cost_viewable_ecpm_advertiser_currency": "METRIC_MEDIA_COST_VIEWABLE_ECPM_ADVERTISER", + "media_cost_viewable_ecpm_partner_currency": "METRIC_MEDIA_COST_VIEWABLE_ECPM_PARTNER", + "media_cost_viewable_ecpm_usd": "METRIC_MEDIA_COST_VIEWABLE_ECPM_USD", + "media_fee_1_advertiser_currency": "METRIC_MEDIA_FEE1_ADVERTISER", + "media_fee_1_partner_currency": "METRIC_MEDIA_FEE1_PARTNER", + "media_fee_1_usd": "METRIC_MEDIA_FEE1_USD", + "media_fee_2_advertiser_currency": "METRIC_MEDIA_FEE2_ADVERTISER", + "media_fee_2_partner_currency": "METRIC_MEDIA_FEE2_PARTNER", + "media_fee_2_usd": "METRIC_MEDIA_FEE2_USD", + "media_fee_3_advertiser_currency": "METRIC_MEDIA_FEE3_ADVERTISER", + "media_fee_3_partner_currency": "METRIC_MEDIA_FEE3_PARTNER", + "media_fee_3_usd": "METRIC_MEDIA_FEE3_USD", + "media_fee_4_advertiser_currency": "METRIC_MEDIA_FEE4_ADVERTISER", + "media_fee_4_partner_currency": "METRIC_MEDIA_FEE4_PARTNER", + "media_fee_4_usd": "METRIC_MEDIA_FEE4_USD", + "media_fee_5_advertiser_currency": "METRIC_MEDIA_FEE5_ADVERTISER", + "media_fee_5_partner_currency": "METRIC_MEDIA_FEE5_PARTNER", + "media_fee_5_usd": "METRIC_MEDIA_FEE5_USD", + "mediacost_data_fee_advertiser_currency": "METRIC_FEE16_ADVERTISER", + "mediacost_data_fee_partner_currency": "METRIC_FEE16_PARTNER", + "mediacost_data_fee_usd": "METRIC_FEE16_USD", + "midpoint_audio": "METRIC_MIDPOINT_AUDIO", + "midpoint_views_video": "METRIC_RICH_MEDIA_VIDEO_MIDPOINTS", + "moat_video_fee_advertiser_currency": "METRIC_FEE18_ADVERTISER", + "moat_video_fee_partner_currency": "METRIC_FEE18_PARTNER", + "moat_video_fee_usd": "METRIC_FEE18_USD", + "nielsen_digital_ad_ratings_fee_advertiser_currency": "METRIC_FEE19_ADVERTISER", + "nielsen_digital_ad_ratings_fee_partner_currency": "METRIC_FEE19_PARTNER", + "nielsen_digital_ad_ratings_fee_usd": "METRIC_FEE19_USD", + "pauses_audio": "METRIC_PAUSES_AUDIO", + "pauses_video": "METRIC_RICH_MEDIA_VIDEO_PAUSES", + "platform_fee_advertiser_currency": "METRIC_PLATFORM_FEE_ADVERTISER", + "platform_fee_partner_currency": "METRIC_PLATFORM_FEE_PARTNER", + "platform_fee_usd": "METRIC_PLATFORM_FEE_USD", + "platform_fee_rate": "METRIC_PLATFORM_FEE_RATE", + "post_view_conversions__cross_environment": "METRIC_POST_VIEW_CONVERSIONS_CROSS_ENVIRONMENT", + "premium_fee_advertiser_currency": "METRIC_PREMIUM_FEE_ADVERTISER_CURRENCY", + "profit_advertiser_currency": "METRIC_PROFIT_ADVERTISER", + "profit_partner_currency": "METRIC_PROFIT_PARTNER", + "profit_usd": "METRIC_PROFIT_USD", + "profit_ecpm_advertiser_currency": "METRIC_PROFIT_ECPM_ADVERTISER", + "profit_ecpm_partner_currency": "METRIC_PROFIT_ECPM_PARTNER", + "profit_ecpm_usd": "METRIC_PROFIT_ECPM_USD", + "profit_margin": "METRIC_PROFIT_MARGIN", + "profit_viewable_ecpm_advertiser_currency": "METRIC_PROFIT_VIEWABLE_ECPM_ADVERTISER", + "profit_viewable_ecpm_partner_currency": "METRIC_PROFIT_VIEWABLE_ECPM_PARTNER", + "profit_viewable_ecpm_usd": "METRIC_PROFIT_VIEWABLE_ECPM_USD", + "programmatic_guaranteed_impressions_passed_due_to_frequency": "METRIC_PROGRAMMATIC_GUARANTEED_IMPRESSIONS_PASSED_DUE_TO_FREQUENCY", + "programmatic_guaranteed_savings_re_invested_due_to_frequency_advertiser_currency": "METRIC_PROGRAMMATIC_GUARANTEED_SAVINGS_RE_INVESTED_DUE_TO_FREQUENCY_ADVERTISER_CURRENCY", + "refund_billable_cost_advertiser_currency": "METRIC_REFUND_BILLABLE_COST_ADVERTISER_CURRENCY", + "refund_media_cost_advertiser_currency": "METRIC_REFUND_MEDIA_COST_ADVERTISER_CURRENCY", + "refund_platform_fee_advertiser_currency": "METRIC_REFUND_PLATFORM_FEE_ADVERTISER_CURRENCY", + "revenue_advertiser_currency": "METRIC_REVENUE_ADVERTISER", + "revenue_partner_currency": "METRIC_REVENUE_PARTNER", + "revenue_usd": "METRIC_REVENUE_USD", + "revenue_ecpa_advertiser_currency": "METRIC_REVENUE_ECPA_ADVERTISER", + "revenue_ecpa_partner_currency": "METRIC_REVENUE_ECPA_PARTNER", + "revenue_ecpa_pc_advertiser_currency": "METRIC_REVENUE_ECPAPC_ADVERTISER", + "revenue_ecpa_pc_partner_currency": "METRIC_REVENUE_ECPAPC_PARTNER", + "revenue_ecpa_pc_usd": "METRIC_REVENUE_ECPAPC_USD", + "revenue_ecpa_pv_advertiser_currency": "METRIC_REVENUE_ECPAPV_ADVERTISER", + "revenue_ecpa_pv_partner_currency": "METRIC_REVENUE_ECPAPV_PARTNER", + "revenue_ecpa_pv_usd": "METRIC_REVENUE_ECPAPV_USD", + "revenue_ecpa_usd": "METRIC_REVENUE_ECPA_USD", + "revenue_ecpc_advertiser_currency": "METRIC_REVENUE_ECPC_ADVERTISER", + "revenue_ecpc_partner_currency": "METRIC_REVENUE_ECPC_PARTNER", + "revenue_ecpc_usd": "METRIC_REVENUE_ECPC_USD", + "revenue_ecpe_advertiser_currency": "METRIC_TRUEVIEW_AVERAGE_CPE_ADVERTISER", + "revenue_ecpe_partner_currency": "METRIC_TRUEVIEW_AVERAGE_CPE_PARTNER", + "revenue_ecpe_usd": "METRIC_TRUEVIEW_AVERAGE_CPE_USD", + "revenue_ecpm_advertiser_currency": "METRIC_REVENUE_ECPM_ADVERTISER", + "revenue_ecpm_partner_currency": "METRIC_REVENUE_ECPM_PARTNER", + "revenue_ecpm_usd": "METRIC_REVENUE_ECPM_USD", + "revenue_ecpv_advertiser_currency": "METRIC_TRUEVIEW_CPV_ADVERTISER", + "revenue_ecpv_partner_currency": "METRIC_TRUEVIEW_CPV_PARTNER", + "revenue_ecpv_usd": "METRIC_TRUEVIEW_CPV_USD", + "revenue_viewable_ecpm_advertiser_currency": "METRIC_REVENUE_VIEWABLE_ECPM_ADVERTISER", + "revenue_viewable_ecpm_partner_currency": "METRIC_REVENUE_VIEWABLE_ECPM_PARTNER", + "revenue_viewable_ecpm_usd": "METRIC_REVENUE_VIEWABLE_ECPM_USD", + "rich_media_engagements": "METRIC_RICH_MEDIA_ENGAGEMENTS", + "scrolls": "METRIC_RICH_MEDIA_SCROLLS", + "shoplocal_fee_advertiser_currency": "METRIC_FEE14_ADVERTISER", + "shoplocal_fee_partner_currency": "METRIC_FEE14_PARTNER", + "shoplocal_fee_usd": "METRIC_FEE14_USD", + "skips_video": "METRIC_RICH_MEDIA_VIDEO_SKIPS", + "starts_audio": "METRIC_STARTS_AUDIO", + "starts_video": "METRIC_RICH_MEDIA_VIDEO_PLAYS", + "stops_audio": "METRIC_STOPS_AUDIO", + "teracent_fee_advertiser_currency": "METRIC_FEE8_ADVERTISER", + "teracent_fee_partner_currency": "METRIC_FEE8_PARTNER", + "teracent_fee_usd": "METRIC_FEE8_USD", + "third_party_ad_server_fee_advertiser_currency": "METRIC_FEE2_ADVERTISER", + "third_party_ad_server_fee_partner_currency": "METRIC_FEE2_PARTNER", + "third_party_ad_server_fee_usd": "METRIC_FEE2_USD", + "third_quartile_audio": "METRIC_THIRD_QUARTILE_AUDIO", + "third_quartile_views_video": "METRIC_RICH_MEDIA_VIDEO_THIRD_QUARTILE_COMPLETES", + "timers": "METRIC_TIMERS", + "total_conversions__cross_environment": "METRIC_TOTAL_CONVERSIONS_CROSS_ENVIRONMENT", + "total_display_time": "METRIC_TOTAL_DISPLAY_TIME", + "total_impression_custom_value": "METRIC_TOTAL_IMPRESSION_CUSTOM_VALUE", + "total_interaction_time": "METRIC_TOTAL_INTERACTION_TIME", + "total_media_cost_advertiser_currency": "METRIC_TOTAL_MEDIA_COST_ADVERTISER", + "total_media_cost_partner_currency": "METRIC_TOTAL_MEDIA_COST_PARTNER", + "total_media_cost_usd": "METRIC_TOTAL_MEDIA_COST_USD", + "total_media_cost_ecpa_advertiser_currency": "METRIC_TOTAL_MEDIA_COST_ECPA_ADVERTISER", + "total_media_cost_ecpa_partner_currency": "METRIC_TOTAL_MEDIA_COST_ECPA_PARTNER", + "total_media_cost_ecpa_pc_advertiser_currency": "METRIC_TOTAL_MEDIA_COST_ECPAPC_ADVERTISER", + "total_media_cost_ecpa_pc_partner_currency": "METRIC_TOTAL_MEDIA_COST_ECPAPC_PARTNER", + "total_media_cost_ecpa_pc_usd": "METRIC_TOTAL_MEDIA_COST_ECPAPC_USD", + "total_media_cost_ecpa_pv_advertiser_currency": "METRIC_TOTAL_MEDIA_COST_ECPAPV_ADVERTISER", + "total_media_cost_ecpa_pv_partner_currency": "METRIC_TOTAL_MEDIA_COST_ECPAPV_PARTNER", + "total_media_cost_ecpa_pv_usd": "METRIC_TOTAL_MEDIA_COST_ECPAPV_USD", + "total_media_cost_ecpa_usd": "METRIC_TOTAL_MEDIA_COST_ECPA_USD", + "total_media_cost_ecpc_advertiser_currency": "METRIC_TOTAL_MEDIA_COST_ECPC_ADVERTISER", + "total_media_cost_ecpc_partner_currency": "METRIC_TOTAL_MEDIA_COST_ECPC_PARTNER", + "total_media_cost_ecpc_usd": "METRIC_TOTAL_MEDIA_COST_ECPC_USD", + "total_media_cost_ecpm_advertiser_currency": "METRIC_TOTAL_MEDIA_COST_ECPM_ADVERTISER", + "total_media_cost_ecpm_partner_currency": "METRIC_TOTAL_MEDIA_COST_ECPM_PARTNER", + "total_media_cost_ecpm_usd": "METRIC_TOTAL_MEDIA_COST_ECPM_USD", + "total_media_cost_viewable_ecpm_advertiser_currency": "METRIC_TOTAL_MEDIA_COST_VIEWABLE_ECPM_ADVERTISER", + "total_media_cost_viewable_ecpm_partner_currency": "METRIC_TOTAL_MEDIA_COST_VIEWABLE_ECPM_PARTNER", + "total_media_cost_viewable_ecpm_usd": "METRIC_TOTAL_MEDIA_COST_VIEWABLE_ECPM_USD", + "total_video_media_cost_ecpcv_advertiser_currency": "METRIC_TOTAL_MEDIA_COST_ECPCV_ADVERTISER", + "total_video_media_cost_ecpcv_partner_currency": "METRIC_TOTAL_MEDIA_COST_ECPCV_PARTNER", + "total_video_media_cost_ecpcv_usd": "METRIC_TOTAL_MEDIA_COST_ECPCV_USD", + "tracked_ads": "METRIC_TRACKED_ADS", + "trueview_general_invalid_traffic_givt_views": "METRIC_TRUEVIEW_GENERAL_INVALID_TRAFFIC_GIVT_VIEWS", + "trueview_invalid_views": "METRIC_TRUEVIEW_INVALID_VIEWS", + "trustmetrics_fee_advertiser_currency": "METRIC_FEE15_ADVERTISER", + "trustmetrics_fee_partner_currency": "METRIC_FEE15_PARTNER", + "trustmetrics_fee_usd": "METRIC_FEE15_USD", + "verifiable_impressions": "METRIC_VERIFIABLE_IMPRESSIONS", + "video_client_cost_ecpcv_advertiser_currency": "METRIC_VIDEO_CLIENT_COST_ECPCV_ADVERTISER_CURRENCY", + "video_media_cost_ecpcv_advertiser_currency": "METRIC_MEDIA_COST_ECPCV_ADVERTISER", + "video_media_cost_ecpcv_partner_currency": "METRIC_MEDIA_COST_ECPCV_PARTNER", + "video_media_cost_ecpcv_usd": "METRIC_MEDIA_COST_ECPCV_USD", + "vizu_fee_advertiser_currency": "METRIC_FEE6_ADVERTISER", + "vizu_fee_partner_currency": "METRIC_FEE6_PARTNER", + "vizu_fee_usd": "METRIC_FEE6_USD", + "youtube_view_rate": "METRIC_TRUEVIEW_VIEW_RATE", + "youtube_views": "METRIC_TRUEVIEW_VIEWS", + "pct_composition_impressions": "METRIC_DEMO_COMPOSITION_IMPRESSION", + "pct_composition_reach": "METRIC_VIRTUAL_PEOPLE_IMPRESSION_REACH_SHARE_PERCENT", + "pct_population_reach": "METRIC_VIRTUAL_PEOPLE_IMPRESSION_REACH_PERCENT", + "population": "METRIC_DEMO_POPULATION", + "target_rating_points": "METRIC_TARGET_RATING_POINTS", + "unique_reach_viewable_impression_reach": "METRIC_VIRTUAL_PEOPLE_VIEWABLE_IMPRESSION_REACH_BY_DEMO", + "viewable_target_rating_points": "METRIC_VIEWABLE_GROSS_RATING_POINTS", + "viewable_impressions": "METRIC_GRP_CORRECTED_VIEWABLE_IMPRESSIONS", + "pct_viewable_composition_impressions": "METRIC_GRP_CORRECTED_VIEWABLE_IMPRESSIONS_SHARE_PERCENT", + "pct_viewable_composition_reach": "METRIC_VIRTUAL_PEOPLE_VIEWABLE_IMPRESSION_REACH_SHARE_PERCENT", + "pct_viewable_population_reach": "METRIC_VIRTUAL_PEOPLE_VIEWABLE_IMPRESSION_REACH_PERCENT", +} diff --git a/airbyte-integrations/connectors/source-dv-360/source_dv_360/source.py b/airbyte-integrations/connectors/source-dv-360/source_dv_360/source.py index 32333fce66f3..a4e90cac2153 100644 --- a/airbyte-integrations/connectors/source-dv-360/source_dv_360/source.py +++ b/airbyte-integrations/connectors/source-dv-360/source_dv_360/source.py @@ -1,46 +1,35 @@ # -# Copyright (c) 2021 Airbyte, Inc., all rights reserved. +# Copyright (c) 2022 Airbyte, Inc., all rights reserved. # import json from datetime import datetime -from typing import Any, Dict, Generator, List, Mapping, MutableMapping, Tuple +from typing import Any, Generator, List, Mapping, MutableMapping, Tuple from airbyte_cdk.logger import AirbyteLogger -from airbyte_cdk.models import ( - AirbyteCatalog, - AirbyteMessage, - AirbyteRecordMessage, - AirbyteStateMessage, - AirbyteStream, - ConfiguredAirbyteCatalog, - Status, - SyncMode, - Type, -) +from airbyte_cdk.models import AirbyteMessage, AirbyteRecordMessage, AirbyteStateMessage, ConfiguredAirbyteCatalog, SyncMode, Type from airbyte_cdk.sources import AbstractSource from airbyte_cdk.sources.streams import Stream from google.oauth2.credentials import Credentials from googleapiclient.discovery import build -from .streams import AudienceComposition, DBMStream, Floodlight, Reach, Standard, UniqueReachAudience +from .streams import AudienceComposition, Floodlight, Reach, Standard, UniqueReachAudience class SourceDV360(AbstractSource): - - def get_credentials(self,config: json) -> Credentials: + def get_credentials(self, config: json) -> Credentials: """ Get the credentials from the config file and returns them as a Credentials object """ - cred_json= config.get('credentials') - return Credentials( - token= cred_json.get('access_token'), - refresh_token= cred_json.get('refresh_token'), - token_uri= cred_json.get('token_uri'), - client_id= cred_json.get('client_id'), - client_secret= cred_json.get('client_secret') + cred_json = config.get("credentials") + creds = Credentials( + token=cred_json.get("access_token"), + refresh_token=cred_json.get("refresh_token"), + token_uri=cred_json.get("token_uri"), + client_id=cred_json.get("client_id"), + client_secret=cred_json.get("client_secret"), ) - + return creds def check_connection(self, logger: AirbyteLogger, config: Mapping[str, Any]) -> Tuple[bool, any]: """ @@ -55,38 +44,39 @@ def check_connection(self, logger: AirbyteLogger, config: Mapping[str, Any]) -> :return: AirbyteConnectionStatus indicating a Success or Failure """ try: - dbm_service= build('doubleclickbidmanager','v1.1', credentials=self.get_credentials(config)) - request= dbm_service.queries().listqueries().execute() - return True, None + dbm_service = build("doubleclickbidmanager", "v1.1", credentials=self.get_credentials(config)) + request = dbm_service.queries().listqueries().execute() + if request: + return True, None except Exception as err: return False, f"Unable to connect to Google Ads API with the provided credentials - {repr(err)}" - def streams(self, config: Mapping[str, Any]) -> List[Stream]: """ :param config: The user-provided configuration as specified by the source's spec. Any stream construction related operation should happen here. :return: A list of the streams in this source connector. """ - args= dict( + args = dict( credentials=self.get_credentials(config), - partner_id= config.get('partner_id'), - start_date= config.get('start_date'), - end_date= config.get('end_date'), - filters= config.get('filters') - ) + partner_id=config.get("partner_id"), + start_date=config.get("start_date"), + end_date=config.get("end_date"), + filters=config.get("filters"), + ) - streams= [ + streams = [ Reach(**args), - Standard(**args), + Standard(**args), AudienceComposition(**args), Floodlight(**args), UniqueReachAudience(**args), ] return streams - - - def read(self, logger: AirbyteLogger, config: json, catalog: ConfiguredAirbyteCatalog, state: MutableMapping[str, Any]) -> Generator[AirbyteMessage, None, None]: + + def read( + self, logger: AirbyteLogger, config: json, catalog: ConfiguredAirbyteCatalog, state: MutableMapping[str, Any] + ) -> Generator[AirbyteMessage, None, None]: """ Returns a generator of the AirbyteMessages generated by reading the source with the given configuration, catalog, and state. @@ -106,45 +96,45 @@ def read(self, logger: AirbyteLogger, config: json, catalog: ConfiguredAirbyteCa :return: A generator that produces a stream of AirbyteRecordMessage contained in AirbyteMessage object. """ - stream_instances= {s.name: s for s in self.streams(config)} + stream_instances = {s.name: s for s in self.streams(config)} for configured_stream in catalog.streams: - stream_name= configured_stream.stream.name - stream_instance= stream_instances.get(stream_name) + stream_name = configured_stream.stream.name + stream_instance = stream_instances.get(stream_name) if not stream_instance: raise KeyError( - f"The requested stream {stream_name} was not found in the source." - f" Available streams: {stream_instances.keys()}" + f"The requested stream {stream_name} was not found in the source." f" Available streams: {stream_instances.keys()}" ) - stream_state= state.get(stream_name, {}) - #if stream_state and "state" in dir(stream_instance): - stream_instance.state= stream_state + stream_state = state.get(stream_name, {}) + # if stream_state and "state" in dir(stream_instance): + stream_instance.state = stream_state logger.info(f"Syncing {stream_name} stream") logger.info(f"Setting state of {stream_name} stream to {stream_state}") yield AirbyteMessage(type=Type.STATE, state=AirbyteStateMessage(data=state)) try: - config_catalog_fields= configured_stream.stream.json_schema.get('properties').keys() - slices= stream_instance.stream_slices( - cursor_field= configured_stream.cursor_field, - sync_mode= SyncMode.incremental, - stream_state= stream_state, + config_catalog_fields = configured_stream.stream.json_schema.get("properties").keys() + slices = stream_instance.stream_slices( + cursor_field=configured_stream.cursor_field, + sync_mode=SyncMode.incremental, + stream_state=stream_state, ) for _slice in slices: - data= stream_instance.read_records( + data = stream_instance.read_records( sync_mode=SyncMode.incremental, - catalog_fields= config_catalog_fields, + catalog_fields=config_catalog_fields, stream_slice=_slice, - stream_state= stream_state, - cursor_field= configured_stream.cursor_field or None, + stream_state=stream_state, + cursor_field=configured_stream.cursor_field or None, ) - #data= stream_instance.read_records(catalog_fields= config_catalog_fields, sync_mode= SyncMode.incremental, stream_slice= _slice) + # data= stream_instance.read_records(catalog_fields= config_catalog_fields, sync_mode= SyncMode.incremental, stream_slice= _slice) for row in data: yield AirbyteMessage( - type= Type.RECORD, - record= AirbyteRecordMessage(stream= stream_name, data= row, emitted_at= int(datetime.now().timestamp()) * 1000)) + type=Type.RECORD, + record=AirbyteRecordMessage(stream=stream_name, data=row, emitted_at=int(datetime.now().timestamp()) * 1000), + ) yield self._checkpoint_state(stream_instance, stream_state, state) logger.info(f"Finished syncing {stream_name} stream") except Exception as e: - logger.error('Failed to read the data: '+ repr(e)) + logger.error("Failed to read the data: " + repr(e)) diff --git a/airbyte-integrations/connectors/source-dv-360/source_dv_360/streams.py b/airbyte-integrations/connectors/source-dv-360/source_dv_360/streams.py index 1ee388bb02c5..f16c4c7f5e05 100644 --- a/airbyte-integrations/connectors/source-dv-360/source_dv_360/streams.py +++ b/airbyte-integrations/connectors/source-dv-360/source_dv_360/streams.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2021 Airbyte, Inc., all rights reserved. +# Copyright (c) 2022 Airbyte, Inc., all rights reserved. # @@ -8,7 +8,6 @@ import json from abc import ABC from typing import Any, Iterable, List, Mapping, MutableMapping, Optional, Tuple -from xmlrpc.client import Boolean import pendulum import requests @@ -25,330 +24,375 @@ "reach": "TYPE_REACH_AND_FREQUENCY", "floodlight": "FLOODLIGHT", "standard": "TYPE_GENERAL", - "unique_reach_audience": "TYPE_REACH_AUDIENCE" + "unique_reach_audience": "TYPE_REACH_AUDIENCE", } + def chunk_date_range( - start_date: str, - field: str, - end_date: str = None, - range_days: int = None, + start_date: str, + field: str, + end_date: str = None, + range_days: int = None, ) -> Iterable[Mapping[str, any]]: - """ - Passing optional parameter end_date for testing - Returns a list of the beginning and ending timestamps of each `range_days` between the start date and now. - The return value is a list of dicts {'date': str} which can be used directly with the Slack API - """ - intervals = [] - end_date = pendulum.parse(end_date) if end_date else pendulum.yesterday() - start_date = pendulum.parse(start_date) - - #to return some state when state is abnormal - if start_date > end_date: - start_date = end_date - - while start_date < end_date: - intervals.append( - { - "start_date": start_date.to_date_string(), - "end_date": end_date.to_date_string(), - } - ) - start_date = start_date.add(days=range_days) - return intervals - -class DBM: - QUERY_TEMPLATE_PATH = "source_dv_360/queries/query_template.json" #Template for creating the query object - DBM_SCOPE = 'doubleclickbidmanager' #Scope required to fetch data - - def __init__(self, credentials: Credentials, partner_id: str, scope: str = DBM_SCOPE, version: str = 'v1.1'): - self.service = build(scope,version, credentials= credentials) #build a service with scope dbm - self.partner_id = partner_id - - @staticmethod - def get_date_params_ms(start_date: str, end_date: str = None) -> Tuple[str, str]: """ - Returns `start_date` and `end_date` in milliseconds + Passing optional parameter end_date for testing + Returns a list of the beginning and ending timestamps of each `range_days` between the start date and now. + The return value is a list of dicts {'date': str} which can be used directly with the Slack API """ - start_date = pendulum.parse(start_date) - # if end_date is null, take date until yesterday + intervals = [] end_date = pendulum.parse(end_date) if end_date else pendulum.yesterday() + start_date = pendulum.parse(start_date) - # check if start date is after end date + # to return some state when state is abnormal if start_date > end_date: - start_date = end_date + start_date = end_date - start_date_ms = str(int(start_date.timestamp() * 1000)) - end_date_ms = str(int(end_date.timestamp() * 1000)) - - return start_date_ms, end_date_ms + while start_date < end_date: + intervals.append( + { + "start_date": start_date.to_date_string(), + "end_date": end_date.to_date_string(), + } + ) + start_date = start_date.add(days=range_days) + return intervals - @staticmethod - def get_fields_from_schema(schema: Mapping[str, Any], catalog_fields: List[str]) -> List[str]: - """ - Get list of fields in a given schema - :param schema: the list of fields to be converted - :param catalog_fields: the list of fields to be converted - :return: A list of fields - """ - schema_fields = schema.get('properties').keys() - fields = [field for field in schema_fields if field in catalog_fields] - return fields +class DBM: + QUERY_TEMPLATE_PATH = "source_dv_360/queries/query_template.json" # Template for creating the query object + DBM_SCOPE = "doubleclickbidmanager" # Scope required to fetch data + + def __init__(self, credentials: Credentials, partner_id: str, scope: str = DBM_SCOPE, version: str = "v1.1"): + self.service = build(scope, version, credentials=credentials) # build a service with scope dbm + self.partner_id = partner_id + + @staticmethod + def get_date_params_ms(start_date: str, end_date: str = None) -> Tuple[str, str]: + """ + Returns `start_date` and `end_date` in milliseconds + """ + start_date = pendulum.parse(start_date) + # if end_date is null, take date until yesterday + end_date = pendulum.parse(end_date) if end_date else pendulum.yesterday() + + # check if start date is after end date + if start_date > end_date: + start_date = end_date + + start_date_ms = str(int(start_date.timestamp() * 1000)) + end_date_ms = str(int(end_date.timestamp() * 1000)) + + return start_date_ms, end_date_ms + + @staticmethod + def get_fields_from_schema(schema: Mapping[str, Any], catalog_fields: List[str]) -> List[str]: + """ + Get list of fields in a given schema + :param schema: the list of fields to be converted + :param catalog_fields: the list of fields to be converted + + :return: A list of fields + """ + schema_fields = schema.get("properties").keys() + fields = [field for field in schema_fields if field in catalog_fields] + return fields + + @staticmethod + def convert_fields(fields: List[str]) -> List[str]: + """ + Convert a list of fields into the API naming + :param fields: the list of fields to be converted + + :return: A list of converted fields + """ + return [API_REPORT_BUILDER_MAPPING[key] for key in fields] + + @staticmethod + def get_dimensions_from_fields(fields: List[str]) -> List[str]: + """ + Get a list of dimensions from a list of fields. Dimensions start with FILTER_ + :param fields: A list of fields from the stream + + :return: A list of dimensions in the naming form of the API + """ + conv_fields = DBM.convert_fields(fields) + dimensions = [field for field in conv_fields if field.startswith("FILTER")] + return dimensions + + @staticmethod + def get_metrics_from_fields(fields: List[str]) -> List[str]: + """ + Get a list of metrics from from a list of fields. Metrics start with METRIC_ + :param fields: A list of fields from the stream + + :return: A list of metrics in the naming form of the API + """ + conv_fields = DBM.convert_fields(fields) + metrics = [field for field in conv_fields if field.startswith("METRIC")] + return metrics + + @staticmethod + def set_partner_filter(query: Mapping[str, Any], partner_id: str): + """ + set the partner id filter to the partner id in the config + :param query: the query object where the filter is to be set + """ + filters = query.get("params").get("filters") + if filters: + partner_filter_index = next( + (index for (index, filter) in enumerate(filters) if filter["type"] == "FILTER_PARTNER"), None + ) # get the index of the partner filter + if partner_filter_index is not None: + query["params"]["filters"][partner_filter_index]["value"] = partner_id # set filter to the partner id in the config + + @staticmethod + def create_query_object( + report_name: str, + dimensions: List[str], + metrics: List[str], + partner_id: str, + start_date: str, + end_date: str, + filters: List[dict] = [], + ) -> Mapping[str, Any]: + """ + Create a query object using the query template and a list of parameter for the query + :param report_name: Name of the report + :param dimensions: List of dimensions + :param metrics: list of metrics + :param start_date: Start date of the report, in the same form of the date in the config, as specified in the spec + :param end_date: End date of the report, in the same form of the date in the config, as specified in the spec + :param filters: additional filters to be set + + :return the query object created according to the template + """ + with open(DBM.QUERY_TEMPLATE_PATH, "r") as template: + query_body = json.loads(template.read()) + + # get dates in ms + start_date_ms, end_date_ms = DBM.get_date_params_ms(start_date, end_date) + + DBM.set_partner_filter(query_body, partner_id) # Set partner Id in the filter + query_body["metadata"]["title"] = report_name + query_body["params"]["type"] = REPORT_TYPE_MAPPING[report_name] # get the report type from the mapping + query_body["params"]["groupBys"] = dimensions # dimensions are put in the groupBy section of the query + query_body["params"]["filters"].extend(filters) # Add additional filters if needed + query_body["params"]["metrics"] = metrics + query_body["reportDataStartTimeMs"] = start_date_ms + query_body["reportDataEndTimeMs"] = end_date_ms + return query_body + + def convert_schema_into_query( + self, + schema: Mapping[str, Any], + report_name: str, + catalog_fields: List[str], + partner_id: str, + filters: List[dict], + start_date: str, + end_date: str, + ) -> str: + """ + Create and run a query from the given schema + :param report_name: Name of the report + :param catalog_fields: List of fields which names are sanitized + :param start_date: Start date of the report, in the same form of the date in the config, as specified in the spec + :param end_date: End date of the report, in the same form of the date in the config, as specified in the spec + :param filters: additional filters to be set + + :return the query object created according to the template + """ + fields = self.get_fields_from_schema(schema, catalog_fields) + query = self.create_query_object( + report_name=report_name, + dimensions=self.get_dimensions_from_fields(fields), + metrics=self.get_metrics_from_fields(fields), + start_date=start_date, + end_date=end_date, + partner_id=partner_id, + filters=filters or [], + ) + create_query = self.service.queries().createquery(body=query).execute() # Create query + get_query = ( + self.service.queries().getquery(queryId=create_query.get("queryId")).execute() + ) # get the query which will include the report url + return get_query - @staticmethod - def convert_fields(fields:List[str]) -> List[str]: +class DBMStream(Stream, ABC): """ - Convert a list of fields into the API naming - :param fields: the list of fields to be converted - - :return: A list of converted fields + Base stream class """ - return [API_REPORT_BUILDER_MAPPING[key] for key in fields] - @staticmethod - def get_dimensions_from_fields(fields: List[str]) -> List[str]: - """ - Get a list of dimensions from a list of fields. Dimensions start with FILTER_ - :param fields: A list of fields from the stream + primary_key = None + + def __init__(self, credentials: Credentials, partner_id: str, filters: List[dict], start_date: str, end_date: str = None): + self.dbm = DBM(credentials=credentials, partner_id=partner_id) + self._start_date = start_date + self._end_date = end_date + self._partner_id = partner_id + self._filters = filters + + def get_query(self, catalog_fields: List[str], stream_slice: Mapping[str, Any]) -> Iterable[Mapping]: + """ + Create and run a query from the datastream schema and parameters, and a list of fields provided in the configured catalog + :param catalog_fields: A list of fields provided in the configured catalog + + :return the created query + """ + query = self.dbm.convert_schema_into_query( + schema=self.get_json_schema(), + catalog_fields=catalog_fields, + filters=self._filters, + report_name=self.name, + start_date=self._start_date, + end_date=self._end_date, + partner_id=self._partner_id, + ) + return query + + def read_records(self, catalog_fields: List[str], stream_slice: Mapping[str, Any] = None, sync_mode=None): + """ + Get the report from the url specified in the created query. The report is in csv form, with + additional meta data below the data that need to be remove. + :param catalog_fields: A list of fields provided in the configured catalog to create the query + + :return a generator of dict rows from the file + """ + query = self.get_query(catalog_fields=catalog_fields, stream_slice=stream_slice) # create and run the query + report_url = query["metadata"]["googleCloudStoragePathForLatestReport"] # Take the url of the generated report + with io.StringIO(requests.get(report_url).text) as csv_response: + header = csv_response.readline().split(",") # get the header of the file + header = [sanitize(field) for field in header] # sanitize the field names + data = self.buffer_reader(csv_response) # Remove the unnecessary rows that do not have data + reader = csv.DictReader(data, fieldnames=header) # convert csv data into dict rows to be yielded by the generator + report_type = query["params"]["type"] + list_reader = list(reader) + nb_rows = len(list_reader) + for index, row in enumerate(list_reader): + # In the case of the standard report, we are getting an additional summary row, therefore we need to exclude it. + if not (report_type == "TYPE_GENERAL" and index > nb_rows - 2): + yield row + + def buffer_reader(self, buffer: io.StringIO): + """ + Yield all lines from a file text buffer until the empty line is reached + + :return a generator of dict rows from the file + """ + for line in buffer.readlines(): + if line != "\n": # NB: the last non empty line contains the sum of the metrics in the data + yield line + else: + break - :return: A list of dimensions in the naming form of the API - """ - conv_fields = DBM.convert_fields(fields) - dimensions = [field for field in conv_fields if field.startswith('FILTER')] - return dimensions - @staticmethod - def get_metrics_from_fields(fields: List[str]) -> List[str]: - """ - Get a list of metrics from from a list of fields. Metrics start with METRIC_ - :param fields: A list of fields from the stream +class DBMIncrementalStream(DBMStream, ABC): + cursor_field = "date" + primary_key = None + range_days = 30 # range of stream slice + + def __init__(self, credentials: Credentials, partner_id: str, filters: List[dict], start_date: str, end_date: str = None): + super().__init__(credentials, partner_id, filters, start_date, end_date) + + def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]: + """ + Update stream state from latest record + """ + current_stream_state = current_stream_state or {} + record_value = latest_record[self.cursor_field] + state_value = current_stream_state.get(self.cursor_field) or record_value + max_cursor = max(pendulum.parse(state_value), pendulum.parse(record_value)) + toreturn = { + self.cursor_field: max_cursor.to_date_string(), + } + return toreturn + + def stream_slices(self, stream_state: Mapping[str, Any] = None, **kwargs) -> Iterable[Optional[Mapping[str, any]]]: + """ + Slice the stream by date periods. + """ + stream_state = stream_state or {} + start_date = stream_state.get(self.cursor_field) or self._start_date + date_chunks = chunk_date_range( + start_date=start_date, + end_date=self._end_date, + field=self.cursor_field, + range_days=self.range_days, + ) + for chunk in date_chunks: + yield chunk + + def read_records( + self, + sync_mode: SyncMode, + catalog_fields: List[str], + cursor_field: List[str] = None, + stream_slice: Mapping[str, Any] = None, + stream_state: Mapping[str, Any] = None, + ) -> Iterable[Mapping[str, Any]]: + """ + This method is overridden to update `start_date` key in the `stream_slice` with the latest read record's cursor value. + """ + records = super().read_records(catalog_fields=catalog_fields, sync_mode=sync_mode, stream_slice=stream_slice) + for record in records: + self.state = self.get_updated_state(self.state, record) + yield record + + def get_query(self, catalog_fields: List[str], stream_slice: Mapping[str, Any]) -> Iterable[Mapping]: + """ + Create and run a query from the datastream schema and parameters, and a list of fields provided in the configured catalog + :param catalog_fields: A list of fields provided in the configured catalog + + :return the created query + """ + query = self.dbm.convert_schema_into_query( + schema=self.get_json_schema(), + catalog_fields=catalog_fields, + filters=self._filters, + report_name=self.name, + start_date=stream_slice.get("start_date"), + end_date=stream_slice.get("end_date"), + partner_id=self._partner_id, + ) + return query - :return: A list of metrics in the naming form of the API - """ - conv_fields = DBM.convert_fields(fields) - metrics = [field for field in conv_fields if field.startswith('METRIC')] - return metrics - @staticmethod - def set_partner_filter(query: Mapping[str, Any], partner_id: str): - """ - set the partner id filter to the partner id in the config - :param query: the query object where the filter is to be set - """ - filters = query.get("params").get("filters") - if filters: - partner_filter_index = next((index for (index, filter) in enumerate(filters) if filter["type"] == "FILTER_PARTNER"), None) #get the index of the partner filter - if partner_filter_index is not None: - query["params"]["filters"][partner_filter_index]["value"] = partner_id #set filter to the partner id in the config - - @staticmethod - def create_query_object(report_name:str, dimensions:List[str], metrics:List[str], partner_id: str, - start_date:str, end_date:str, filters:List[dict] = []) -> Mapping[str, Any]: - """ - Create a query object using the query template and a list of parameter for the query - :param report_name: Name of the report - :param dimensions: List of dimensions - :param metrics: list of metrics - :param start_date: Start date of the report, in the same form of the date in the config, as specified in the spec - :param end_date: End date of the report, in the same form of the date in the config, as specified in the spec - :param filters: additional filters to be set - - :return the query object created according to the template - """ - with open(DBM.QUERY_TEMPLATE_PATH, 'r') as template: - query_body = json.loads(template.read()) - - # get dates in ms - start_date_ms, end_date_ms = DBM.get_date_params_ms(start_date, end_date) - - DBM.set_partner_filter(query_body, partner_id) #Set partner Id in the filter - query_body["metadata"]["title"] = report_name - query_body["params"]["type"] = REPORT_TYPE_MAPPING[report_name] #get the report type from the mapping - query_body["params"]["groupBys"] = dimensions #dimensions are put in the groupBy section of the query - query_body["params"]["filters"].extend(filters) #Add additional filters if needed - query_body["params"]["metrics"] = metrics - query_body["reportDataStartTimeMs"] = start_date_ms - query_body["reportDataEndTimeMs"] = end_date_ms - return query_body - - def convert_schema_into_query(self, schema: Mapping[str, Any], report_name: str, catalog_fields: List[str], partner_id: str, filters:List[dict], start_date: str, end_date: str) -> str: +class AudienceComposition(DBMIncrementalStream): """ - Create and run a query from the given schema - :param report_name: Name of the report - :param catalog_fields: List of fields which names are sanitized - :param start_date: Start date of the report, in the same form of the date in the config, as specified in the spec - :param end_date: End date of the report, in the same form of the date in the config, as specified in the spec - :param filters: additional filters to be set - - :return the query object created according to the template + Audience Composition stream """ - fields = self.get_fields_from_schema(schema,catalog_fields) - query = self.create_query_object( - report_name = report_name, - dimensions = self.get_dimensions_from_fields(fields), - metrics = self.get_metrics_from_fields(fields), - start_date = start_date, - end_date = end_date, - partner_id = partner_id, - filters = filters or [], - ) - create_query = self.service.queries().createquery(body=query).execute() #Create query - get_query = self.service.queries().getquery(queryId=create_query.get('queryId')).execute() #get the query which will include the report url - return get_query + primary_key = None -class DBMStream(Stream, ABC): - """ - Base stream class - """ - primary_key = None - - def __init__(self, credentials: Credentials, partner_id: str, filters:List[dict], start_date: str, end_date: str=None): - self.dbm = DBM(credentials= credentials, partner_id=partner_id) - self._start_date = start_date - self._end_date = end_date - self._partner_id = partner_id - self._filters = filters - - def get_query(self, catalog_fields: List[str], stream_slice:Mapping[str, Any]) -> Iterable[Mapping]: - """ - Create and run a query from the datastream schema and parameters, and a list of fields provided in the configured catalog - :param catalog_fields: A list of fields provided in the configured catalog - :return the created query - """ - query = self.dbm.convert_schema_into_query(schema= self.get_json_schema(),catalog_fields=catalog_fields, filters= self._filters,report_name= self.name, - start_date=self._start_date, end_date=self._end_date, partner_id = self._partner_id) - return query - - def read_records(self,catalog_fields: List[str],stream_slice: Mapping[str, Any]=None, sync_mode= None): - """ - Get the report from the url specified in the created query. The report is in csv form, with - additional meta data below the data that need to be remove. - :param catalog_fields: A list of fields provided in the configured catalog to create the query - - :return a generator of dict rows from the file +class Floodlight(DBMIncrementalStream): """ - query = self.get_query(catalog_fields = catalog_fields, stream_slice = stream_slice) # create and run the query - report_url = query['metadata']['googleCloudStoragePathForLatestReport'] # Take the url of the generated report - with io.StringIO(requests.get(report_url).text) as csv_response: - header = csv_response.readline().split(',') #get the header of the file - header = [sanitize(field) for field in header] #sanitize the field names - data = self.buffer_reader(csv_response) # Remove the unnecessary rows that do not have data - reader = csv.DictReader(data, fieldnames=header) #convert csv data into dict rows to be yielded by the generator - report_type = query["params"]["type"] - list_reader = list(reader) - nb_rows = len(list_reader) - for index, row in enumerate(list_reader): - # In the case of the standard report, we are getting an additional summary row, therefore we need to exclude it. - if not (report_type == "TYPE_GENERAL" and index > nb_rows - 2): - yield row - - - def buffer_reader(self, buffer:io.StringIO): + Floodlight stream """ - Yield all lines from a file text buffer until the empty line is reached - :return a generator of dict rows from the file - """ - for line in buffer.readlines(): - if line != '\n': # NB: the last non empty line contains the sum of the metrics in the data - yield line - else: - break + primary_key = None -class DBMIncrementalStream(DBMStream, ABC): - cursor_field = "date" - primary_key = None - range_days = 30 #range of stream slice - - def __init__(self, credentials: Credentials, partner_id: str, filters:List[dict], start_date: str, end_date: str=None): - super().__init__(credentials, partner_id, filters, start_date, end_date) - - def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]: - """ - Update stream state from latest record - """ - current_stream_state = current_stream_state or {} - record_value = latest_record[self.cursor_field] - state_value = current_stream_state.get(self.cursor_field) or record_value - max_cursor = max(pendulum.parse(state_value), pendulum.parse(record_value)) - toreturn = { - self.cursor_field: max_cursor.to_date_string(), - } - return toreturn - - def stream_slices(self, stream_state: Mapping[str, Any] = None, **kwargs) -> Iterable[Optional[Mapping[str, any]]]: - """ - Slice the stream by date periods. - """ - stream_state = stream_state or {} - start_date = stream_state.get(self.cursor_field) or self._start_date - date_chunks = chunk_date_range( - start_date = start_date, - end_date = self._end_date, - field = self.cursor_field, - range_days = self.range_days, - ) - for chunk in date_chunks: - yield chunk - - def read_records( - self, - sync_mode: SyncMode, - catalog_fields: List[str], - cursor_field: List[str] = None, - stream_slice: Mapping[str, Any] = None, - stream_state: Mapping[str, Any] = None, - ) -> Iterable[Mapping[str, Any]]: - """ - This method is overridden to update `start_date` key in the `stream_slice` with the latest read record's cursor value. +class Standard(DBMIncrementalStream): """ - records = super().read_records(catalog_fields = catalog_fields, sync_mode = sync_mode, stream_slice = stream_slice) - for record in records: - self.state = self.get_updated_state(self.state, record) - yield record - - def get_query(self, catalog_fields: List[str], stream_slice:Mapping[str, Any]) -> Iterable[Mapping]: + Standard stream """ - Create and run a query from the datastream schema and parameters, and a list of fields provided in the configured catalog - :param catalog_fields: A list of fields provided in the configured catalog - :return the created query - """ - query = self.dbm.convert_schema_into_query(schema = self.get_json_schema(),catalog_fields = catalog_fields, filters = self._filters,report_name= self.name, - start_date = stream_slice.get("start_date"), end_date = stream_slice.get("end_date"), partner_id = self._partner_id) - return query + primary_key = None -class AudienceComposition(DBMIncrementalStream): - """ - Audience Composition stream - """ - primary_key = None -class Floodlight(DBMIncrementalStream): - """ - Floodlight stream - """ - primary_key = None +class UniqueReachAudience(DBMIncrementalStream): + """ + Unique Reach Audience stream + """ -class Standard(DBMIncrementalStream): - """ - Standard stream - """ - primary_key = None + primary_key = None -class UniqueReachAudience(DBMIncrementalStream): - """ - Unique Reach Audience stream - """ - primary_key = None class Reach(DBMIncrementalStream): - """ - Reach stream - """ - primary_key = None \ No newline at end of file + """ + Reach stream + """ + + primary_key = None diff --git a/airbyte-integrations/connectors/source-dv-360/unit_tests/conftest.py b/airbyte-integrations/connectors/source-dv-360/unit_tests/conftest.py index 4a283d00a8d2..c40a4656127d 100644 --- a/airbyte-integrations/connectors/source-dv-360/unit_tests/conftest.py +++ b/airbyte-integrations/connectors/source-dv-360/unit_tests/conftest.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2021 Airbyte, Inc., all rights reserved. +# Copyright (c) 2022 Airbyte, Inc., all rights reserved. # import json @@ -10,4 +10,4 @@ @pytest.fixture(scope="session", name="config") def config_fixture(): with open("secrets/config.json", "r") as config_file: - return json.load(config_file) \ No newline at end of file + return json.load(config_file) diff --git a/airbyte-integrations/connectors/source-dv-360/unit_tests/test_fields.py b/airbyte-integrations/connectors/source-dv-360/unit_tests/test_fields.py index b71b58f56c56..90427c9c63e9 100644 --- a/airbyte-integrations/connectors/source-dv-360/unit_tests/test_fields.py +++ b/airbyte-integrations/connectors/source-dv-360/unit_tests/test_fields.py @@ -1,50 +1,53 @@ # -# Copyright (c) 2021 Airbyte, Inc., all rights reserved. +# Copyright (c) 2022 Airbyte, Inc., all rights reserved. # from source_dv_360.fields import sanitize def test_sanitize_with_pct(): - string = '% tesT string:' + string = "% tesT string:" sanitized_string = sanitize(string) - expected_result = 'pct_test_string' + expected_result = "pct_test_string" assert sanitized_string == expected_result def test_sanitize_trailing_space(): - string = '% tesT string: ' + string = "% tesT string: " sanitized_string = sanitize(string) - expected_result = 'pct_test_string' + expected_result = "pct_test_string" assert sanitized_string == expected_result def test_sanitize_leading_space(): - string = ' % tesT string:' + string = " % tesT string:" sanitized_string = sanitize(string) - expected_result = 'pct_test_string' + expected_result = "pct_test_string" assert sanitized_string == expected_result + def test_sanitize_punctuation(): - string = '% tesT string:,;()#$' + string = "% tesT string:,;()#$" sanitized_string = sanitize(string) - expected_result = 'pct_test_string' + expected_result = "pct_test_string" assert sanitized_string == expected_result + def test_sanitize_slash(): - string = '% tesT string:/test' + string = "% tesT string:/test" sanitized_string = sanitize(string) - expected_result = 'pct_test_string_test' + expected_result = "pct_test_string_test" assert sanitized_string == expected_result + def test_sanitize_and(): - string = '% tesT string & test' + string = "% tesT string & test" sanitized_string = sanitize(string) - expected_result = 'pct_test_string_and_test' + expected_result = "pct_test_string_and_test" - assert sanitized_string == expected_result \ No newline at end of file + assert sanitized_string == expected_result diff --git a/airbyte-integrations/connectors/source-dv-360/unit_tests/test_source.py b/airbyte-integrations/connectors/source-dv-360/unit_tests/test_source.py index 41dcef8572e2..6eaf41620916 100644 --- a/airbyte-integrations/connectors/source-dv-360/unit_tests/test_source.py +++ b/airbyte-integrations/connectors/source-dv-360/unit_tests/test_source.py @@ -1,30 +1,21 @@ # -# Copyright (c) 2021 Airbyte, Inc., all rights reserved. +# Copyright (c) 2022 Airbyte, Inc., all rights reserved. # -from google.oauth2.credentials import Credentials from source_dv_360.source import SourceDV360 - -def test_streams_count(config): - source = SourceDV360() - streams = source.streams(config) - expected_streams_number = 5 - assert len(streams) == expected_streams_number - - SAMPLE_CONFIG = { - "credentials": { - "access_token": "access_token", - "refresh_token": "refresh_token", - "token_uri": "uri", - "client_id": "client_id", - "client_secret": "client_secret" - }, - "start_date": "2022-03-01", - "end_date": "2022-03-08", - "partner_id": 123, - "filters": [] + "credentials": { + "access_token": "access_token", + "refresh_token": "refresh_token", + "token_uri": "uri", + "client_id": "client_id", + "client_secret": "client_secret", + }, + "start_date": "2022-03-01", + "end_date": "2022-03-08", + "partner_id": 123, + "filters": [], } @@ -33,7 +24,7 @@ def test_streams_count(config): "refresh_token": "refresh_token", "token_uri": "uri", "client_id": "client_id", - "client_secret": "client_secret" + "client_secret": "client_secret", } @@ -41,8 +32,8 @@ def test_get_credentials(): client = SourceDV360() credentials = client.get_credentials(SAMPLE_CONFIG) - assert credentials.token == 'access_token' - assert credentials.refresh_token == 'refresh_token' - assert credentials.token_uri == 'uri' - assert credentials.client_id == 'client_id' - assert credentials.client_secret == 'client_secret' \ No newline at end of file + assert credentials.token == "access_token" + assert credentials.refresh_token == "refresh_token" + assert credentials.token_uri == "uri" + assert credentials.client_id == "client_id" + assert credentials.client_secret == "client_secret" diff --git a/airbyte-integrations/connectors/source-dv-360/unit_tests/test_streams.py b/airbyte-integrations/connectors/source-dv-360/unit_tests/test_streams.py index dd338d66cdc6..4f4edd144882 100644 --- a/airbyte-integrations/connectors/source-dv-360/unit_tests/test_streams.py +++ b/airbyte-integrations/connectors/source-dv-360/unit_tests/test_streams.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2021 Airbyte, Inc., all rights reserved. +# Copyright (c) 2022 Airbyte, Inc., all rights reserved. # import json @@ -10,7 +10,13 @@ def test_convert_fields(): fields = ["app_url_id", "cm_placement_id", "pct_clicks_leading_to_conversions", "region_id", "date"] converted_fields = DBM.convert_fields(fields) - expected_fields = ["FILTER_SITE_ID", "FILTER_CM_PLACEMENT_ID", "METRIC_CLICK_TO_POST_CLICK_CONVERSION_RATE", "FILTER_REGION", "FILTER_DATE"] + expected_fields = [ + "FILTER_SITE_ID", + "FILTER_CM_PLACEMENT_ID", + "METRIC_CLICK_TO_POST_CLICK_CONVERSION_RATE", + "FILTER_REGION", + "FILTER_DATE", + ] assert converted_fields == expected_fields @@ -50,7 +56,7 @@ def test_convert_fields(): ] -def test_get_fields_from_schema(): +def test_get_fields_from_schema(): fields = DBM.get_fields_from_schema(SCHEMA, CATALOG_FIELDS) expected_fields = [ "advertiser", @@ -85,7 +91,7 @@ def test_get_fields_from_schema(): assert expected_fields == fields -def test_get_dimensions_from_fields(): +def test_get_dimensions_from_fields(): fields = DBM.get_fields_from_schema(SCHEMA, CATALOG_FIELDS) diemsions = DBM.get_dimensions_from_fields(fields) expected_diemsions = [ @@ -116,7 +122,7 @@ def test_get_dimensions_from_fields(): assert expected_diemsions == diemsions -def test_get_metrics_from_fields(): +def test_get_metrics_from_fields(): fields = DBM.get_fields_from_schema(SCHEMA, CATALOG_FIELDS) metrics = DBM.get_metrics_from_fields(fields) expected_metrics = [ @@ -129,79 +135,66 @@ def test_get_metrics_from_fields(): assert expected_metrics == metrics - EXPECTED_QUERY = { - "kind": "doubleclickbidmanager#query", - "queryId": "0", - "metadata": { - "title": "reach", - "dataRange": "CUSTOM_DATES", - "format": "CSV", - "running": False, - "googleCloudStoragePathForLatestReport": "", - "latestReportRunTimeMs": "0", - "sendNotification": False - }, - "params": { - "type": "TYPE_REACH_AND_FREQUENCY", - "groupBys": [ - "FILTER_ADVERTISER_NAME", - "FILTER_ADVERTISER", - "FILTER_ADVERTISER_INTEGRATION_CODE", - "FILTER_ADVERTISER_INTEGRATION_STATUS", - "FILTER_APP_URL", - "FILTER_MEDIA_PLAN_NAME", - "FILTER_MEDIA_PLAN", - "FILTER_CREATIVE", - "FILTER_CREATIVE_ID", - "FILTER_CREATIVE_SOURCE", - "FILTER_DATE", - "FILTER_INSERTION_ORDER_NAME", - "FILTER_INSERTION_ORDER", - "FILTER_INSERTION_ORDER_INTEGRATION_CODE", - "FILTER_INSERTION_ORDER_STATUS", - "FILTER_INVENTORY_SOURCE_NAME", - "FILTER_LINE_ITEM_NAME", - "FILTER_LINE_ITEM", - "FILTER_LINE_ITEM_STATUS", - "FILTER_PARTNER_NAME", - "FILTER_PARTNER", - "FILTER_PARTNER_STATUS", - "FILTER_TARGETED_DATA_PROVIDERS" - ], - "filters": [ - { - "type": "FILTER_PARTNER", - "value": "123" - }, - { - "type":"FILTER_LINE_ITEM", - "value":55 - } - ], - "metrics": [ - "METRIC_COOKIE_REACH_AVERAGE_IMPRESSION_FREQUENCY", - "METRIC_COOKIE_REACH_IMPRESSION_REACH", - "METRIC_UNIQUE_REACH_AVERAGE_IMPRESSION_FREQUENCY", - "METRIC_UNIQUE_REACH_CLICK_REACH", - "METRIC_UNIQUE_REACH_IMPRESSION_REACH" - ], - "options": { - "includeOnlyTargetedUserLists": False - } - }, - "schedule": { - "frequency": "ONE_TIME" - }, - "reportDataStartTimeMs": "1646092800000", - "reportDataEndTimeMs": "1646697600000", - "timezoneCode": "UTC" + "kind": "doubleclickbidmanager#query", + "queryId": "0", + "metadata": { + "title": "reach", + "dataRange": "CUSTOM_DATES", + "format": "CSV", + "running": False, + "googleCloudStoragePathForLatestReport": "", + "latestReportRunTimeMs": "0", + "sendNotification": False, + }, + "params": { + "type": "TYPE_REACH_AND_FREQUENCY", + "groupBys": [ + "FILTER_ADVERTISER_NAME", + "FILTER_ADVERTISER", + "FILTER_ADVERTISER_INTEGRATION_CODE", + "FILTER_ADVERTISER_INTEGRATION_STATUS", + "FILTER_APP_URL", + "FILTER_MEDIA_PLAN_NAME", + "FILTER_MEDIA_PLAN", + "FILTER_CREATIVE", + "FILTER_CREATIVE_ID", + "FILTER_CREATIVE_SOURCE", + "FILTER_DATE", + "FILTER_INSERTION_ORDER_NAME", + "FILTER_INSERTION_ORDER", + "FILTER_INSERTION_ORDER_INTEGRATION_CODE", + "FILTER_INSERTION_ORDER_STATUS", + "FILTER_INVENTORY_SOURCE_NAME", + "FILTER_LINE_ITEM_NAME", + "FILTER_LINE_ITEM", + "FILTER_LINE_ITEM_STATUS", + "FILTER_PARTNER_NAME", + "FILTER_PARTNER", + "FILTER_PARTNER_STATUS", + "FILTER_TARGETED_DATA_PROVIDERS", + ], + "filters": [{"type": "FILTER_PARTNER", "value": "123"}, {"type": "FILTER_LINE_ITEM", "value": 55}], + "metrics": [ + "METRIC_COOKIE_REACH_AVERAGE_IMPRESSION_FREQUENCY", + "METRIC_COOKIE_REACH_IMPRESSION_REACH", + "METRIC_UNIQUE_REACH_AVERAGE_IMPRESSION_FREQUENCY", + "METRIC_UNIQUE_REACH_CLICK_REACH", + "METRIC_UNIQUE_REACH_IMPRESSION_REACH", + ], + "options": {"includeOnlyTargetedUserLists": False}, + }, + "schedule": {"frequency": "ONE_TIME"}, + "reportDataStartTimeMs": "1646092800000", + "reportDataEndTimeMs": "1646697600000", + "timezoneCode": "UTC", } + def test_create_query_object(): query = DBM.create_query_object( - report_name= "reach", - dimensions= [ + report_name="reach", + dimensions=[ "FILTER_ADVERTISER_NAME", "FILTER_ADVERTISER", "FILTER_ADVERTISER_INTEGRATION_CODE", @@ -224,23 +217,18 @@ def test_create_query_object(): "FILTER_PARTNER_NAME", "FILTER_PARTNER", "FILTER_PARTNER_STATUS", - "FILTER_TARGETED_DATA_PROVIDERS" + "FILTER_TARGETED_DATA_PROVIDERS", ], - metrics = [ + metrics=[ "METRIC_COOKIE_REACH_AVERAGE_IMPRESSION_FREQUENCY", "METRIC_COOKIE_REACH_IMPRESSION_REACH", "METRIC_UNIQUE_REACH_AVERAGE_IMPRESSION_FREQUENCY", "METRIC_UNIQUE_REACH_CLICK_REACH", - "METRIC_UNIQUE_REACH_IMPRESSION_REACH" + "METRIC_UNIQUE_REACH_IMPRESSION_REACH", ], - start_date= "2022-03-01", - end_date= "2022-03-08", - partner_id = "123", - filters = [ - { - "type":"FILTER_LINE_ITEM", - "value":55 - } - ] + start_date="2022-03-01", + end_date="2022-03-08", + partner_id="123", + filters=[{"type": "FILTER_LINE_ITEM", "value": 55}], ) - assert query == EXPECTED_QUERY \ No newline at end of file + assert query == EXPECTED_QUERY diff --git a/airbyte-integrations/connectors/source-dv-360/unit_tests/unit_test.py b/airbyte-integrations/connectors/source-dv-360/unit_tests/unit_test.py index e1814314fc3b..dddaea0060fa 100644 --- a/airbyte-integrations/connectors/source-dv-360/unit_tests/unit_test.py +++ b/airbyte-integrations/connectors/source-dv-360/unit_tests/unit_test.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2021 Airbyte, Inc., all rights reserved. +# Copyright (c) 2022 Airbyte, Inc., all rights reserved. #