google-ads-python: Unable to create sitelinks for ad group in bulk (batch job)

UPDATE: Partially solved. Please see following comment.

Hi! Is that possible to create sitelinks and assign them into ad group in the same Batch Job?

I have a method that creates a sitelink extension like this:

    def _get_extension_feed_item_resource_name(self, feed_item_id: str) -> str:
        """
        Returns resource_name for Extension Feed Item by ID

        :param feed_item_id: Feed item ID
        :return: Feed item resource name
        """
        extension_feed_item_service = self.client.get_service(
            "ExtensionFeedItemService", version=GOOGLE_ADS_API_VERSION
        )
        return extension_feed_item_service.extension_feed_item_path(self.customer_id, feed_item_id)

    def _build_ad_group_sitelink_extension_operation(
        self, ad_group_resource_name: str, link_text: str, final_url: str
    ) -> ExtensionFeedItemOperation:
        """
        Helper method that creates sitelink extension feed item for ad group.

        :param ad_group_resource_name: Ad Group resource name
        :param link_text: Link text
        :param final_url: Target URL
        :return: ExtensionFeedItemOperation
        """
        extension_type_enum = self.client.get_type("ExtensionTypeEnum")
        extension_feed_item_operation = self.client.get_type(
            "ExtensionFeedItemOperation", version=GOOGLE_ADS_API_VERSION
        )
        extension_feed_item = extension_feed_item_operation.create
        extension_feed_item.extension_type = extension_type_enum.SITELINK
        extension_feed_item.sitelink_feed_item.link_text = link_text
        extension_feed_item.targeted_ad_group = ad_group_resource_name
        extension_feed_item.sitelink_feed_item.final_urls.append(final_url)
        # Creates a resource name using the temporary ID.
        feed_item_id = str(self._get_next_temporary_id())
        extension_feed_item.resource_name = self._get_extension_feed_item_resource_name(feed_item_id)

        return extension_feed_item_operation

So I’m creating few sitelinks using _build_ad_group_sitelink_extension_operation method and then I’m trying to assign them into ad group using

# looping through link items ...
extension_feed_item_operation = self._build_ad_group_sitelink_extension_operation(
                    ad_group_resource_name=ad_group_resource_name,
                    link_text=item["text"],
                    final_url=item["url"],
                )
link_resource_id = extension_feed_item_operation.create.resource_name
# memorizing link_resource_id for AdGroupExtensionSettingOperation

Feed item resource names looks the following:

Out[19]:
['customers/<hidden>/extensionFeedItems/-10',
 'customers/<hidden>/extensionFeedItems/-18',
 'customers/<hidden>/extensionFeedItems/-26',
 'customers/<hidden>/extensionFeedItems/-34']

and then I’m creating AdGroupExtensionSettingOperation

    def _build_ad_group_extension_settings_operation(
        self, ad_group_resource_name: str, feed_item_resource_names: List[str]
    ) -> AdGroupExtensionSettingOperation:
        """
        Builds Ad Group extension setting operation
        :param ad_group_resource_name: Ad Group resource name
        :return: AdGroupExtensionSettingOperation
        """
        ad_group_ext_setting_operation = self.client.get_type(
            "AdGroupExtensionSettingOperation", version=GOOGLE_ADS_API_VERSION
        )
        extension_type_enum = self.client.get_type("ExtensionTypeEnum", version=GOOGLE_ADS_API_VERSION)

        ad_group_ext_setting = ad_group_ext_setting_operation.create
        ad_group_ext_setting.ad_group = ad_group_resource_name
        ad_group_ext_setting.extension_type = extension_type_enum.SITELINK
        ad_group_ext_setting.extension_feed_items.extend(feed_item_resource_names)
        return ad_group_ext_setting_operation

finally I’m appending my ExtensionFeedItemOperations and AdGroupExtensionSettingOperation to a batch job;

In [35]: data['operations']['ad_group_links']
Out[35]:
[extension_feed_item_operation {
   create {
     resource_name: "customers/<hidden>/extensionFeedItems/-10"
     sitelink_feed_item {
       link_text: "Buty zimowe"
       final_urls: "https://domaincom/pl/buty-zimowe-damskie/2a/"
     }
     extension_type: SITELINK
     targeted_ad_group: "customers/<hidden>/adGroups/-3"
   }
 },
 ad_group_extension_setting_operation {
   create {
     extension_type: SITELINK
     ad_group: "customers/<hidden>/adGroups/-3"
     extension_feed_items: "customers/<hidden>/extensionFeedItems/-10"
   }
 },
 extension_feed_item_operation {
   create {
     resource_name: "customers/<hidden>/extensionFeedItems/-18"
     sitelink_feed_item {
       link_text: "Buty zimowe"
       final_urls: "https://domaincom/pl/buty-zimowe-damskie/2a__zapiecie-buta-zamek/"
     }
     extension_type: SITELINK
     targeted_ad_group: "customers/<hidden>/adGroups/-11"
   }
 },
 ad_group_extension_setting_operation {
   create {
     extension_type: SITELINK
     ad_group: "customers/<hidden>/adGroups/-11"
     extension_feed_items: "customers/<hidden>/extensionFeedItems/-18"
   }
 },
 extension_feed_item_operation {
   create {
     resource_name: "customers/<hidden>/extensionFeedItems/-26"
     sitelink_feed_item {
       link_text: "Kozaki damskie"
       final_urls: "https://domaincom/pl/kozaki-damskie/2a/"
     }
     extension_type: SITELINK
     targeted_ad_group: "customers/<hidden>/adGroups/-19"
   }
 },
 ad_group_extension_setting_operation {
   create {
     extension_type: SITELINK
     ad_group: "customers/<hidden>/adGroups/-19"
     extension_feed_items: "customers/<hidden>/extensionFeedItems/-26"
   }
 },
 extension_feed_item_operation {
   create {
     resource_name: "customers/<hidden>/extensionFeedItems/-34"
     sitelink_feed_item {
       link_text: "Kozaki damskie"
       final_urls: "https://domaincom/pl/kozaki-damskie/2a__zapiecie-buta-zamek/"
     }
     extension_type: SITELINK
     targeted_ad_group: "customers/<hidden>/adGroups/-27"
   }
 },
 ad_group_extension_setting_operation {
   create {
     extension_type: SITELINK
     ad_group: "customers/<hidden>/adGroups/-27"
     extension_feed_items: "customers/<hidden>/extensionFeedItems/-34"
   }
 }]

The response from batch job contains the following error:

Batch job #50 has a status "Field 'resource_name' cannot be modified by 'CREATE' operation., at mutate_operations[50].extension_feed_item_operation.create.resource_name" and response type "N/A"
Batch job #51 has a status "Multiple errors in ‘details’. First error: Field must be set., at mutate_operations[51].ad_group_extension_setting_operation" and response type "N/A"

So it looks like I cannot use temporary IDs for feed items? What should I do differently to create feed items and assign into ad group in a single Batch Job then?

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 33 (9 by maintainers)

Most upvoted comments

All I got was a private response that went like this:

I can confirm that this is an issue at our end. It is related to how Batch jobs handle ExtensionFeedItem. We will work on a fix, but it might take a while. If it is not critical for you to use Batch jobs, you can use GoogleAdsService::Mutate() instead. That service should handle the same set of operations correctly.

That is, I think we might expect an update in v7 of the API whenever that comes out, and until then, no Batch Jobs with temporary IDs for extensions, have to work with Mutates and their responses.