Example #1
0
    def _validate_credentials(self) -> None:
        """Validate credentials.

    Raises:
      DataOutConnectorValueError: If credential combination does not meet
        criteria.
    """
        if not self.api_secret:
            raise errors.DataOutConnectorAuthenticationError(
                'Missing api secret. Please check you have api_secret set as a Cloud '
                'Composer variable as specified in the TCRM documentation.')

        valid_payload_types = (PayloadTypes.FIREBASE.value,
                               PayloadTypes.GTAG.value)
        if self.payload_type not in valid_payload_types:
            raise errors.DataOutConnectorError(
                f'Unsupport payload_type: {self.payload_type}. Supported '
                'payload_type is gtag or firebase.')

        if (self.payload_type == PayloadTypes.FIREBASE.value
                and not self.firebase_app_id):
            raise errors.DataOutConnectorError(
                'Wrong payload_type or missing firebase_app_id. Please make sure '
                'firebase_app_id is set when payload_type is firebase.')

        if (self.payload_type == PayloadTypes.GTAG.value
                and not self.measurement_id):
            raise errors.DataOutConnectorError(
                'Wrong payload_type or missing measurement_id. Please make sure '
                'measurement_id is set when payload_type is gtag.')
Example #2
0
    def add_offline_conversions(
            self, payload: List[Mapping[Text, Any]]) -> Dict[str, Any]:
        """Uploads offline conversions.

    The uploaded results represents as partial failures. For detail:
    https://developers.google.com/adwords/api/docs/guides/partial-failure

    Args:
      payload: The offline conversions to uplad.

    Returns:
      The partial failures.

    Raises:
      DataOutConnectorAuthenticationError raised when authentication errors
      occurred.
    """
        service = self._get_service(
            ServiceType.OFFLINE_CONVERSION_FEED_SERVICE, True)
        try:
            partial_failures = service.mutate(payload)
        except (googleads_errors.GoogleAdsServerFault,
                google_auth_exceptions.RefreshError) as error:
            raise errors.DataOutConnectorAuthenticationError(
                error=error,
                msg=
                'Failed to add offline conversions due to authentication error.',
                error_num=(errors.ErrorNameIDMap.
                           RETRIABLE_ERROR_OUTPUT_AUTHENTICATION_FAILED))
        return partial_failures
Example #3
0
    def create_user_list(
            self,
            user_list_name: Text,
            upload_key_type: UploadKeyType = UploadKeyType.CONTACT_INFO,
            membership_lifespan: int = MEMBERSHIP_LIFESPAN_DAYS,
            app_id: Optional[Text] = None) -> int:
        """Creates a new user list.

    Args:
      user_list_name: The name of the user list to upload.
      upload_key_type: One of the keys listed in UploadKeyType.
      membership_lifespan: Number of days a user's cookie stays.
      app_id: Mobile app id for creating user list.

    Returns:
      The ID of the new user list.

    Raises:
      DataOutConnectorAuthenticationError raised when authentication errors
      occurred.
      DataOutConnectorValueError if a new user list cannot be created.
    """
        service = self._get_service(ServiceType.ADWORDS_USER_LIST_SERVICE)
        new_user_list = {
            'xsi_type': 'CrmBasedUserList',
            'name': user_list_name,
            'description':
            'A list of users uploaded from Adwords API via TCRM',
            'membershipLifeSpan': membership_lifespan,
            'uploadKeyType': upload_key_type.name,
        }

        operations = [{'operator': 'ADD', 'operand': new_user_list}]
        try:
            result = service.mutate(operations)
        except (googleads_errors.GoogleAdsServerFault,
                googleads_errors.GoogleAdsValueError,
                google_auth_exceptions.RefreshError) as error:
            raise errors.DataOutConnectorAuthenticationError(
                error=error,
                msg='Failed to create user list due to authentication error.',
                error_num=(errors.ErrorNameIDMap.
                           RETRIABLE_ERROR_OUTPUT_AUTHENTICATION_FAILED))

        if (upload_key_type == UploadKeyType.MOBILE_ADVERTISING_ID
                and app_id is not None):
            new_user_list['appId'] = app_id

        if 'value' in result and len(result['value']):
            return result['value'][0]['id']
        else:
            raise errors.DataOutConnectorError(
                msg='Failed to create user list. (response error)',
                error_num=(errors.ErrorNameIDMap.
                           RETRIABLE_ADS_HOOK_ERROR_FAIL_CREATING_USER_LIST))
Example #4
0
    def get_user_list_id(self, user_list_name: Text) -> int:
        """Converts user list name to user list ID.

    Searches for a ServiceType.AdwordsUserListService list in Google Ads and
    returns the list's ID if it exists and raises an error if it doesn't exist.

    Args:
      user_list_name: The name of the user list to get the ID for.

    Returns:
      user_list_id: ID of the user list.

    Raises:
      DataOutConnectorAuthenticationError raised when authentication errors
      occurred.
      DataOutConnectorValueError if the list with given user list name doesn't
      exist.
    """
        user_list_meta_data_selector = {
            'fields': ['Name', 'Id'],
            'predicates': [{
                'field': 'Name',
                'operator': 'EQUALS',
                'values': user_list_name
            }, {
                'field': 'ListType',
                'operator': 'EQUALS',
                'values': 'CRM_BASED'
            }],
        }
        service = self._get_service(ServiceType.ADWORDS_USER_LIST_SERVICE)

        try:
            result = service.get(user_list_meta_data_selector)
        except (googleads_errors.GoogleAdsServerFault,
                googleads_errors.GoogleAdsValueError,
                google_auth_exceptions.RefreshError) as error:
            raise errors.DataOutConnectorAuthenticationError(
                error=error,
                msg='Failed to get user list ID due to authentication error.',
                error_num=(errors.ErrorNameIDMap.
                           RETRIABLE_ERROR_OUTPUT_AUTHENTICATION_FAILED))

        if 'entries' in result and len(result['entries']):
            user_list_id = result['entries'][0]['id']
        else:
            raise errors.DataOutConnectorValueError(
                msg="""Failed to get user list ID. List doesn't exist""",
                error_num=errors.ErrorNameIDMap.
                ADS_HOOK_ERROR_FAIL_TO_GET_USER_LIST_ID)

        return user_list_id
Example #5
0
    def _get_service(
            self,
            service_type: ServiceType,
            enable_partial_failure: bool = False) -> common.GoogleSoapService:
        """Gets AdWords service according to the given service type.

    Partial failure detailed explanation:
    https://developers.google.com/adwords/api/docs/guides/partial-failure

    Args:
      service_type: AdWords service to create a service client for. See all
        available services in ServiceType.
      enable_partial_failure: A flag to allow request that valid operations be
        committed and failed ones return errors.

    Returns:
      AdWords service object.

    Raises:
      DataOutConnectorAuthenticationError raised when authentication errors
      occurred.
      DataOutConnectorValueError if the service can't be created.
    """
        try:
            adwords_client = adwords.AdWordsClient.LoadFromString(
                self.yaml_doc)
            adwords_client.partial_failure = enable_partial_failure
        except googleads_errors.GoogleAdsValueError as error:
            raise errors.DataOutConnectorAuthenticationError(
                error=error,
                msg=
                ('Please check the credentials in the yml doc, it should contains'
                 ' a top level key named adwords and 5 sub key-value'
                 ' pairs named client_customer_id, developer_token, client_id,'
                 ' client_secret and refresh_token.'),
                error_num=(errors.ErrorNameIDMap.
                           RETRIABLE_ERROR_OUTPUT_AUTHENTICATION_FAILED))

        try:
            service = adwords_client.GetService(service_type.value,
                                                self.api_version)
        except googleads_errors.GoogleAdsValueError as error:
            raise errors.DataOutConnectorValueError(
                error=error,
                msg='Couldn\'t get service from Google Adwords API',
                error_num=errors.ErrorNameIDMap.
                RETRIABLE_ADS_HOOK_ERROR_UNAVAILABLE_ADS_SERVICE)
        return service
Example #6
0
    def add_members_to_user_list(self, user_list_id: int,
                                 payload: List[Dict[str, Any]]) -> None:
        """Adds new members to a Google Ads user list.

    Args:
      user_list_id: The ID of the user list to upload.
      payload: A batch of payload data that will be sent to AdWords API.

    Raises:
      DataOutConnectorAuthenticationError raised when authentication errors
      occurred.
      DataOutConnectorSendUnsuccessfulError if the member list uploaded haven't
      been processed successfully by the API.
    """
        service = self._get_service(ServiceType.ADWORDS_USER_LIST_SERVICE)
        mutate_members_operation = {
            'operand': {
                'userListId': user_list_id,
                'membersList': payload
            },
            'operator': 'ADD'
        }

        try:
            response = service.mutateMembers([mutate_members_operation])
        except (googleads_errors.GoogleAdsServerFault,
                google_auth_exceptions.RefreshError) as error:
            raise errors.DataOutConnectorAuthenticationError(
                error=error,
                msg=
                'Failed to add members to user list due to authentication error.',
                error_num=(errors.ErrorNameIDMap.
                           RETRIABLE_ERROR_OUTPUT_AUTHENTICATION_FAILED))

        try:
            if response['userLists'][0]['dataUploadResult'] == 'FAILURE':
                raise errors.DataOutConnectorSendUnsuccessfulError(
                    'Failed to add members to the user list.',
                    error_num=errors.ErrorNameIDMap.
                    RETRIABLE_ADS_HOOK_ERROR_FAIL_ADDING_MEMBERS_TO_USER_LIST)
        except (KeyError, IndexError):
            raise errors.DataOutConnectorSendUnsuccessfulError(
                'Failed to add members to the user list.',
                error_num=errors.ErrorNameIDMap.
                RETRIABLE_ADS_HOOK_ERROR_FAIL_ADDING_MEMBERS_TO_USER_LIST)