googleads / google-ads-php

Google Ads API Client Library for PHP
https://developers.google.com/google-ads/api/docs/client-libs/php
Apache License 2.0
280 stars 260 forks source link

Helper class for printing `Asset` info from a `SearchAdsResponse` object #1034

Closed jtj9817 closed 1 month ago

jtj9817 commented 2 months ago

Problem you are trying to solve: There's a helper function in the examples called printResponseDetails, This is very handy when using printing details from a mutateGoogleAdsResponse object. However, there's no equivalent for a SearchAdsResponse object, specifically when iterating through the results and you want information of an asset. Consider:

    public function getSitelinks(Request $request)
    {
             $this->validateCustomerId($request->all());
            $customer_id = $request->input('customer_id');
            $googleAdsServiceClient = $this->getGoogleAdsServiceClient();

        try {
            $sitelinks = [];
            $query = "SELECT asset.sitelink_asset.ad_schedule_targets, asset.sitelink_asset.description1, asset.sitelink_asset.description2, asset.sitelink_asset.end_date, asset.sitelink_asset.link_text, asset.sitelink_asset.start_date FROM asset
        WHERE asset.policy_summary.approval_status = 'APPROVED' AND asset.source = 'ADVERTISER'";
            $response = $googleAdsServiceClient->search(SearchGoogleAdsRequest::build($customer_id, $query), ['returnTotalResultsCount' => true]);
            foreach ($response->iterateAllElements() as $googleAdsRow) {
                $siteLink = $googleAdsRow->getAsset()->getSitelinkAsset();
                if ($siteLink != null) {
                    $sitelinks[] = [
                        'link_text' => $siteLink->getLinkText(),
                        'description1' => $siteLink->getDescription1(),
                        'description2' => $siteLink->getDescription2(),
                        'start_date' => $siteLink->getStartDate(),
                        'end_date' => $siteLink->getEndDate(),
                        'resource_name' => $googleAdsRow->getAsset()->getResourceName(),
                    ];
                }
            }
            return response()->json(['site_links' => $sitelinks], 200);return response()->json(['site_links' => $sitelinks], 200);
        } catch (\Exception $e) {
            return response()->json(['error' => "Error occurred! " . $e->getMessage()], 422);
        }
    }
    public function getAdCallouts(Request $request)
    {
        //Same as before
        try {
            $callouts = [];
            $query = "SELECT asset.callout_asset.ad_schedule_targets, asset.callout_asset.callout_text, asset.callout_asset.end_date, asset.callout_asset.start_date FROM asset WHERE asset.policy_summary.approval_status = 'APPROVED' AND customer.status = 'ENABLED' AND asset.source = 'ADVERTISER'";
            $response = $googleAdsServiceClient->search(SearchGoogleAdsRequest::build($customer_id, $query), ['returnTotalResultsCount' => true]);
            foreach ($response->iterateAllElements() as $googleAdsRow) {
                $callout = $googleAdsRow->getAsset()->getCalloutAsset();
                if ($callout != null) {
                    $callouts[] = [
                        'callout_text' => $callout->getCalloutText(),
                    ];
                }
            }
            return response()->json(['callouts' => $callouts], 200);
        } catch (\Exception $e) {
            return response()->json(['error' => "Error occurred! " . $e->getMessage()], 422);
        }
    }

These 2 functions are pretty similar in structure. The only differences are the fields being handled as well as the values. From the googleAdsRow->getAsset()->getCallAsset() object, there's an attribute called name_to_field under the desc which gives the fields and the getter and setter functions for each field. Perhaps there could be a generic way to print all the fields? Solution you'd like: A Helper class for SearchAdsResponse object that determines the type of asset, its fields, values, and the appropriate enums for a value if needed. Alternatives you've considered: I have to manually figure out the enums and the fields.

fiboknacky commented 2 months ago

Theoretically, name_to_field could be used to print all fields available and infer the getter and setter of each field. But it belongs to the internal implementation of the Protobuf class, which can be changed at any time, so I doubt it's a reliable enough to be used to create a generic util for this Google Ads API library. That sounds more like a generic util for the Protobuf repo.

We can leave this open as an feature request for now, but to be honest, this would take long time until we can schedule time to implement this.

jtj9817 commented 2 months ago

I think this issue can be closed. The goal was to print all the fields and values for a given Asset and the serializeToJsonString() works just fine for this use case. For example:

 public function getAdWordsSnippets(Request $request)
    {
        $this->validateCustomerId($request->all());
        $customer_id = $request->input('customer_id');
        $googleAdsServiceClient = $this->getGoogleAdsServiceClient();
        try {
            $structured_snippets = [];
            $query = "SELECT asset.structured_snippet_asset.header, asset.structured_snippet_asset.values FROM asset WHERE asset.source = 'ADVERTISER' AND asset.policy_summary.approval_status = 'APPROVED'";
            $response = $googleAdsServiceClient->search(SearchGoogleAdsRequest::build($customer_id, $query), ['returnTotalResultsCount' => true]);
            foreach ($response->iterateAllElements() as $googleAdsRow) {
                if ($googleAdsRow->getAsset() != null && $googleAdsRow->getAsset()->getStructuredSnippetAsset() != null) {
                    $structured_snippets[] = json_decode($googleAdsRow->getAsset()->serializeToJsonString(), true);
                }
            }
            return response()->json(['structured_snippets' => $structured_snippets], 200);
        } catch (\Exception $e) {
            return response()->json(['error' => "Error occurred! " . $e->getMessage()], 422);
        }
    }

Output:

image

So this can be closed, unless there's enough warrant for this helper class to be formalized as part of Google Ads API.

fiboknacky commented 1 month ago

Thanks for confirming. serializeToJson() should handle this case very well.