googleads / google-ads-ruby Goto Github PK
View Code? Open in Web Editor NEWGoogle Ads API Ruby Client Library
Home Page: https://developers.google.com/google-ads/api/
License: Apache License 2.0
Google Ads API Ruby Client Library
Home Page: https://developers.google.com/google-ads/api/
License: Apache License 2.0
When the ads client is initialized it's possible to have the default logger fail to be created. The client will return but will fail on subsequent calls in which the LoggingInterceptor is invoked. I would expect the LoggingInterceptor to just never be used if no logger is set
google-ads-ruby/lib/google/ads/google_ads/google_ads_client.rb
Lines 78 to 83 in 50e510c
google-ads-ruby/lib/google/ads/google_ads/google_ads_client.rb
Lines 99 to 109 in 50e510c
On doing UserListService.mutate_user_lists with insert for a similar user list is failing with "Creating user list without setting type in oneof user_list field, or creating/updating read-only user list types is not allowed.", the type of user list was set to :SIMILAR
request:
[{:create=><Google::Ads::GoogleAds::V1::Resources::UserList: resource_name: "", id: nil, read_only: nil, name: <Google::Protobuf::StringValue: value: "ppagi audience 2019-06-25T14:39:15-04:00">, description: <Google::Protobuf::StringValue: value: "ppagi description 2019-06-25T14:39:15-04:00">, membership_status: :OPEN, integration_code: nil, membership_life_span: <Google::Protobuf::Int64Value: value: 180>, size_for_display: nil, size_range_for_display: :UNSPECIFIED, size_for_search: nil, size_range_for_search: :UNSPECIFIED, type: :SIMILAR, closing_reason: :UNSPECIFIED, access_reason: :UNSPECIFIED, account_user_list_status: :UNSPECIFIED, eligible_for_search: nil, eligible_for_display: nil, crm_based_user_list: nil, similar_user_list: <Google::Ads::GoogleAds::V1::Common::SimilarUserListInfo: seed_user_list: <Google::Protobuf::StringValue: value: "customers/4983552381/userLists/6038929100482">>, rule_based_user_list: nil, logical_user_list: nil, basic_user_list: nil>}]
response:
<Google::Ads::GoogleAds::V1::Services::MutateUserListsResponse: results: [<Google::Ads::GoogleAds::V1::Services::MutateUserListResult: resource_name: "">], partial_failure_error: <Google::Rpc::Status: code: 3, message: "Creating user list without setting type in oneof user_list field, or creating/updating read-only user list types is not allowed., at operations[0]", details: [<Google::Protobuf::Any: type_url: "type.googleapis.com/google.ads.googleads.v1.errors.GoogleAdsFailure", value: "\n\x9E\x01\n\x03\xF0\x04\x10\x12\x80\x01Creating user list without setting type in oneof user_list field, or creating/updating read-only user list types is not allowed.\x1A\x02*\x00"\x10\x12\x0E\n\noperations\x12\x00">]>>
I initially reported these in the forum but they told me to post here.
I would like to report some glitches I faced while implementing google ads code using https://github.com/googleads/google-ads-ruby
Basically it's a matter of documentation stating entities are editable while they are not (or maybe partially, yet would deserve clarification).
I put below the list of entities we did check alongside the error messages we got:
Keywords: 'keyword.match_type' cannot be modified by 'UPDATE'
so we cant rely on mere update
AdCustomizerFeedMapping: bug in the gem maybe, cannot update: undefined method
update=' for #<Google::Ads::GoogleAds::V1::Services::FeedMappingOperation:0x00007f211f40b540`
Location: Field 'location.geo_target_constant' cannot be modified by 'UPDATE' operation โ Field 'negative' cannot be modified by 'UPDATE' operation.
Proximity: 'proximity.geo_point.latitude_in_micro_degrees' cannot be modified by 'UPDATE' --Field 'proximity.radius' cannot be modified by 'UPDATE'
etc...
ExpandedTextAd: Field 'ad.expanded_text_ad.description' cannot be modified by 'UPDATE' operation., at operations[0].update.ad.expanded_text_ad.description", details: [<Google::Protobuf::Any: type_url: "type.googleapis.com/google.ads.googleads.v1.errors.GoogleAdsFailure", value: "\n\x9C\x01\n\x02\b\v\x12QField 'ad.expanded_text_ad.description' cannot be modified by 'UPDATE' operation.\"C\x12\x0E\n\noperations\x12\x00\x12\b\n\x06update\x12\x04\n\x02ad\x12\x12\n\x10expanded_text_ad\x12\r\n\vdescription\n\xA2\x01\n\x02\b\v\x12TField 'ad.expanded_text_ad.headline_part1' cannot be modified by 'UPDATE' operation.\"F\x12\x0E\n\noperations\x12\x00\x12\b\n\x06update\x12\x04\n\x02ad\x12\x12\n\x10expanded_text_ad\x12\x10\n\x0Eheadline_part1\n\xA2\x01\n\x02\b\v\x12TField 'ad.expanded_text_ad.headline_part2' cannot be modified by 'UPDATE' operation.\"F\x12\x0E\n\noperations\x12\x00\x12\b\n\x06update\x12\x04\n\x02ad\x12\x12\n\x10expanded_text_ad\x12\x10\n\x0Eheadline_part2\n\x90\x01\n\x02\b\v\x12KField 'ad.expanded_text_ad.path1' cannot be modified by 'UPDATE' operation.\"=\x12\x0E\n\noperations\x12\x00\x12\b\n\x06update\x12\x04\n\x02ad\x12\x12\n\x10expanded_text_ad\x12\a\n\x05path1\n\x90\x01\n\x02\b\v\x12KField 'ad.expanded_text_ad.path2' cannot be modified by 'UPDATE' operation.\"=\x12\x0E\n\noperations\x12\x00\x12\b\n\x06update\x12\x04\n\x02ad\x12\x12\n\x10expanded_text_ad\x12\a\n\x05path2\nu\n\x02\b\v\x12?Field 'ad.final_urls' cannot be modified by 'UPDATE' operation.\".\x12\x0E\n\noperations\x12\x00\x12\b\n\x06update\x12\x04\n\x02ad\x12\f\n\nfinal_urls">]
AdCustomizerFeed: The customer is not eligible to mutate this resource.
Yet delete/create work fine
CampaignAdSchedule: Field 'ad_schedule.day_of_week' cannot be modified by 'UPDATE' operation., at operations[1].update.ad_schedule.day_of_week", details: [<Google::Protobuf::Any: type_url: "type.googleapis.com/google.ads.googleads.v1.errors.GoogleAdsFailure", value: "\n\x8B\x01\n\x02\b\v\x12IField 'ad_schedule.day_of_week' cannot be modified by 'UPDATE' operation.\":\x12\x10\n\noperations\x12\x02\b\x01\x12\b\n\x06update\x12\r\n\vad_schedule\x12\r\n\vday_of_week\n\x85\x01\n\x02\b\v\x12FField 'ad_schedule.end_hour' cannot be modified by 'UPDATE' operation.\"7\x12\x10\n\noperations\x12\x02\b\x01\x12\b\n\x06update\x12\r\n\vad_schedule\x12\n\n\bend_hour\n\x89\x01\n\x02\b\v\x12HField 'ad_schedule.end_minute' cannot be modified by 'UPDATE' operation.\"9\x12\x10\n\noperations\x12\x02\b\x01\x12\b\n\x06update\x12\r\n\vad_schedule\x12\f\n\nend_minute\n\x89\x01\n\x02\b\v\x12HField 'ad_schedule.start_hour' cannot be modified by 'UPDATE' operation.\"9\x12\x10\n\noperations\x12\x02\b\x01\x12\b\n\x06update\x12\r\n\vad_schedule\x12\f\n\nstart_hour\n\x8D\x01\n\x02\b\v\x12JField 'ad_schedule.start_minute' cannot be modified by 'UPDATE' operation.\"
After the v0.7 update, the method "get_customer" of customer service is not working and it gets an error:
undefined method 'customer_id' for #<Google::Ads::GoogleAds::V0::Services::GetCustomerRequest>
You can check it in the "get_account_information.rb" example. Thanks.
Hello, I try to set partial_failure in the method
campaign_service =client.service(:Campaign)
campaign_service.mutate_campaigns(externalCustomerId,campaignOperatio,true)
but this fail:
**/usr/local/rvm/gems/ruby-2.5.1/gems/google-ads-googleads-0.7.0/lib/google/ads/google_ads/v0/services/campaign_service_client.rb:250:in mutate_campaigns': wrong number of arguments (given 3, expected 2) (ArgumentError)** as it says here
https://developers.google.com/google-ads/api/reference/rpc/google.ads.googleads.v0.services#google.ads.googleads.v0.services.MutateCampaignsRequest`
It does have a create and remove entry, and customer_client_link has all 3, as do most other resource types. For some reason customer_manager_link
operation is missing an "update" entry in the factories.
Hello, the last commit fixes one error but it raises another now, this happens because the file "recommendation_service_pb.rb" inside the v0/services folder is auto-generated incorrectly and needs changes to work properly.
That's why my pull request had changes inside v0 folder the first time.
NameError: uninitialized constant Google::Ads::GoogleAds::V0::Services::DismissRecommendationOperation
It would be great to have a possibility to provide with own interceptors for service initialization since there is currently no way to inject there. Ideally (or additionally) in a global manner so this could be configured without modifying client/service initialization code and interceptor could be injected dynamically in tests (to fake requests).
link: https://developers.google.com/google-ads/api/docs/client-libs/ruby/configuration
In the following section "You can even modify the configuration after instantiation", it needs to be client.configure
instead of client.config
See for example: https://github.com/googleads/google-ads-ruby/blob/master/lib/google/ads/google_ads/v1/services/account_budget_service_client.rb#L78
The lib currently only accepts a refresh token and passes it along as part of the updater_proc, but we could allow the user to specify their credentials in any of the valid formats. We should add a config option to specify this with any custom value the user sets.
Code to reproduce:
require 'google/ads/google_ads'
client = Google::Ads::GoogleAds::GoogleAdsClient.new
client.operation.remove_resource.campaign('whatever')
Output:
NameError (uninitialized constant Google::Ads::GoogleAds::V1::Services::CampaignOperation)
Expected output:
A CampaignOperation
I think we're just missing a "require" inside each remove call.
P1 because we have released a library with a feature that users can't use.
For repeated fields where you append values with <<
, you still need to do client.wrapper.type on the rhs for it to work.
We should also auto-box when appending this way.
Using 3.2.0
, it seems there is a regression within the data I retrieve on errors.
It was possible to get the index of the errored operations before yet this field is now nil
see <Google::Ads::GoogleAds::V2::Errors::ErrorLocation::FieldPathElement: field_name: "name", index: nil>]>
and full object below.
If ever it is relevant, it happens after a mutation where I use partial_failure: true, validate_only: true
.
Is it a known issue?
Thanks
[#<GoogleErrorWrapper:0x00007f682e2904f8 @error=<Google::Ads::GoogleAds::V2::Errors::GoogleAdsError: error_code: <Google::Ads::GoogleAds::V2::Errors::ErrorCode: request_error: :UNSPECIFIED, bidding_strategy_error: :UNSPECIFIED, url_field_error: :UNSPECIFIED, list_operation_error: :UNSPECIFIED, query_error: :UNSPECIFIED, mutate_error: :UNSPECIFIED, field_mask_error: :UNSPECIFIED, authorization_error: :UNSPECIFIED, internal_error: :UNSPECIFIED, quota_error: :UNSPECIFIED, ad_error: :UNSPECIFIED, ad_group_error: :UNSPECIFIED, campaign_budget_error: :DUPLICATE_NAME, campaign_error: :UNSPECIFIED, authentication_error: :UNSPECIFIED, ad_group_criterion_error: :UNSPECIFIED, ad_customizer_error: :UNSPECIFIED, ad_group_ad_error: :UNSPECIFIED, ad_sharing_error: :UNSPECIFIED, adx_error: :UNSPECIFIED, bidding_error: :UNSPECIFIED, campaign_criterion_error: :UNSPECIFIED, collection_size_error: :UNSPECIFIED, criterion_error: :UNSPECIFIED, date_error: :UNSPECIFIED, date_range_error: :UNSPECIFIED, distinct_error: :UNSPECIFIED, feed_attribute_reference_error: :UNSPECIFIED, function_error: :UNSPECIFIED, function_parsing_error: :UNSPECIFIED, id_error: :UNSPECIFIED, image_error: :UNSPECIFIED, media_bundle_error: :UNSPECIFIED, multiplier_error: :UNSPECIFIED, new_resource_creation_error: :UNSPECIFIED, not_empty_error: :UNSPECIFIED, null_error: :UNSPECIFIED, operator_error: :UNSPECIFIED, range_error: :UNSPECIFIED, region_code_error: :UNSPECIFIED, setting_error: :UNSPECIFIED, string_format_error: :UNSPECIFIED, string_length_error: :UNSPECIFIED, operation_access_denied_error: :UNSPECIFIED, resource_access_denied_error: :UNSPECIFIED, resource_count_limit_exceeded_error: :UNSPECIFIED, recommendation_error: :UNSPECIFIED, ad_group_bid_modifier_error: :UNSPECIFIED, context_error: :UNSPECIFIED, field_error: :UNSPECIFIED, shared_set_error: :UNSPECIFIED, shared_criterion_error: :UNSPECIFIED, campaign_shared_set_error: :UNSPECIFIED, conversion_action_error: :UNSPECIFIED, header_error: :UNSPECIFIED, database_error: :UNSPECIFIED, policy_finding_error: :UNSPECIFIED, enum_error: :UNSPECIFIED, keyword_plan_error: :UNSPECIFIED, keyword_plan_campaign_error: :UNSPECIFIED, keyword_plan_negative_keyword_error: :UNSPECIFIED, keyword_plan_ad_group_error: :UNSPECIFIED, keyword_plan_keyword_error: :UNSPECIFIED, keyword_plan_idea_error: :UNSPECIFIED, account_budget_proposal_error: :UNSPECIFIED, user_list_error: :UNSPECIFIED, change_status_error: :UNSPECIFIED, feed_error: :UNSPECIFIED, geo_target_constant_suggestion_error: :UNSPECIFIED, campaign_draft_error: :UNSPECIFIED, feed_item_error: :UNSPECIFIED, label_error: :UNSPECIFIED, media_file_error: :UNSPECIFIED, billing_setup_error: :UNSPECIFIED, customer_client_link_error: :UNSPECIFIED, customer_error: :UNSPECIFIED, customer_manager_link_error: :UNSPECIFIED, feed_mapping_error: :UNSPECIFIED, customer_feed_error: :UNSPECIFIED, ad_group_feed_error: :UNSPECIFIED, campaign_feed_error: :UNSPECIFIED, custom_interest_error: :UNSPECIFIED, campaign_experiment_error: :UNSPECIFIED, extension_feed_item_error: :UNSPECIFIED, ad_parameter_error: :UNSPECIFIED, feed_item_validation_error: :UNSPECIFIED, extension_setting_error: :UNSPECIFIED, feed_item_target_error: :UNSPECIFIED, policy_violation_error: :UNSPECIFIED, asset_error: :UNSPECIFIED, mutate_job_error: :UNSPECIFIED, country_code_error: :UNSPECIFIED, language_code_error: :UNSPECIFIED, conversion_upload_error: :UNSPECIFIED, partial_failure_error: :UNSPECIFIED, policy_validation_parameter_error: :UNSPECIFIED, conversion_adjustment_upload_error: :UNSPECIFIED, media_upload_error: :UNSPECIFIED, youtube_video_registration_error: :UNSPECIFIED, size_limit_error: :UNSPECIFIED, not_whitelisted_error: :UNSPECIFIED, manager_link_error: :UNSPECIFIED, currency_code_error: :UNSPECIFIED, access_invitation_error: :UNSPECIFIED, reach_plan_error: :UNSPECIFIED, invoice_error: :UNSPECIFIED>, message: "A campaign budget with this name already exists.", trigger: <Google::Ads::GoogleAds::V2::Common::Value: boolean_value: false, int64_value: 0, float_value: 0.0, double_value: 0.0, string_value: "">, location: <Google::Ads::GoogleAds::V2::Errors::ErrorLocation: field_path_elements: [<Google::Ads::GoogleAds::V2::Errors::ErrorLocation::FieldPathElement: field_name: "operations", index: nil>, <Google::Ads::GoogleAds::V2::Errors::ErrorLocation::FieldPathElement: field_name: "create", index: nil>, <Google::Ads::GoogleAds::V2::Errors::ErrorLocation::FieldPathElement: field_name: "name", index: nil>]>, details: nil>>]
We should be able to support customizeable timeouts in the library config, with a sane default value
Hello,
I just spotted that there are two hard coded values that should not be in the add_campaign_draft code example:
Thanks,
When attempting to run this example, the following error is raised:
NameError (uninitialized constant Google::Ads::GooglAads)
In Google::Ads::GoogleAds::GoogleAdsClient
, Google::Ads::GoogleAds
is misspelled as Google::Ads::GooglAads
.
I would open a PR to fix this, however I don't have appropriate permissions.
I want to use the new logging capability (which I can do locally but not on my servers). Thanks
I faced Google::Protobuf::TypeError
when execute GoogleAdsService.Mutate
like below.
(Almost as same as example codes to create Campaign and Campaign Budget)
require 'google/ads/google_ads'
customer_id = 'xxxyyyzzzz'
client = Google::Ads::GoogleAds::GoogleAdsClient.new
ga_service = client.service(:GoogleAds)
cbudget = client.resource(:CampaignBudget)
cbudget.id = client.wrapper.int64(-1)
cbudget.name = client.wrapper.string(sprintf('Interplanetary Budget %s',(Time.new.to_f * 1000).to_i))
cbudget.delivery_method = client.enum(:BudgetDeliveryMethod)::STANDARD
cbudget.amount_micros = client.wrapper.int64(500000)
cbudget_operation = client.operation(:CampaignBudget)
cbudget_operation['create'] = cbudget
campaign = client.resource(:Campaign)
campaign.name = client.wrapper.string(sprintf('Interplanetary Cruise %s',(Time.new.to_f * 1000).to_i))
campaign.advertising_channel_type = client.enum(:AdvertisingChannelType)::SEARCH
campaign.status = client.enum(:CampaignStatus)::PAUSED
campaign.manual_cpc = client.resource(:ManualCpc)
campaign.campaign_budget = client.wrapper.string("customers/#{customer_id}/campaignBudgets/-1")
campaign.network_settings = client.resource(:NetworkSettings)
campaign.network_settings.target_google_search = client.wrapper.bool(true)
campaign.network_settings.target_search_network = client.wrapper.bool(true)
campaign.network_settings.target_content_network = client.wrapper.bool(false)
campaign.network_settings.target_partner_search_network = client.wrapper.bool(false)
campaign.start_date = client.wrapper.string(DateTime.parse((Date.today + 1).to_s).strftime('%Y%m%d'))
campaign.end_date = client.wrapper.string(DateTime.parse((Date.today.next_year).to_s).strftime('%Y%m%d'))
campaign_operation = client.operation(:Campaign)
campaign_operation['create'] = campaign
ga_service.mutate(customer_id, [cbudget_operation, campaign_operation])
Finally, ga_service.mutate()
raises Google::Protobuf::TypeError
like below.
(some of stack-trace lines...)
/Users/.../vendor/bundle/ruby/2.5.0/gems/google-gax-1.5.0/lib/google/gax/util.rb:65:in `initialize': Invalid type Google::Ads::GoogleAds::V1::Services::CampaignOperation to assign to submessage field ''. (Google::Protobuf::TypeError)
Do I have something mistake in above sample code? Or GoogleAdsService.Mutate
has something bugs?
campaign.bidding_strategy_type = :MANUAL_CPC
is possible but if submitted as part of a write operation it will fail because bidding_strategy_type is read only. We get back a very confusing error message
/Users/samphippen/.gem/ruby/2.5.3/gems/google-gax-1.5.0/lib/google/gax/api_callable.rb:369:in `rescue in block in retryable': GaxError Exception occurred in retry method that was not classified as transient, caused by 3:Request contains an invalid argument. (Google::Gax::RetryError)
Ideally, it would be impossible to call Campaign#bidding_strategy_type=
to prevent this from happening. It should be possible to define methods as read only in the protos.
Hi,
Now I try to rewrite my API call to feed
and feed_item
operation from Adwords API to Google Ads API.
I have a problem when I call mutate_feed_items
for DYNAMIC_CUSTOM feed, and it seems to be a bug.
My code like the following, ...
# client = Google::Ads::Googleds::GoogleAdsClient instance
# original_feed_item = generate via client.resource.feed_item, attributes from API query result.
operations = []
operation = client.operation.update_resource.feed_item(original_feed_item) do |modify_feed_item|
...
# set values to update
end
if !opearation.update_mask.empty?
operations << operation
end
if !operations.empty?
client.service.feed_item.mutate_feed_items(MY_CUSTOMER_ID, operations)
end
then it raise error Google::Gax::InvalidArgumentError, and logged.
I, [2019-08-07T14:47:16.960735 #76554] INFO -- : Incoming response (errors):
Error 1: {"errorCode":{"fieldError":"FIELD_CANNOT_BE_CLEARED"},"message":"The field cannot be cleared.","location":{"fieldPathElements":[{"fieldName":"operations","index":},{"fieldName":"update"},{"fieldName":"attribute_values"},{"fieldName":"boolean_value"}]}}
...
feed_item
for DYNAMIC_CUSTOM has no field of type boolean
, so it seems to be a bug.
Would it be possible to have an injectable config.logger
(rather than just the stream/level)? We try to reuse Rails.logger
or one of our custom logger instances whenever possible
With adwords api, I would take N operations, do a dry run with partial_failure and validate_only.
Response would give me for each wrong operation: its index, the relevant error.
So I would know exactly which operations were invalid and why, so I could discard them and push the rest.
With google ads, sending 4 operations, 2 with known wrong arguments, I get:
<Google::Ads::GoogleAds::V1::Services::MutateCampaignBudgetsResponse: results: [],
partial_failure_error: <Google::Rpc::Status: code: 3, message: "Multiple errors in โdetailsโ. First
error: Too low., at operations[0].create.amount_micros", details: [<Google::Protobuf::Any:
type_url: "type.googleapis.com/google.ads.googleads.v1.errors.GoogleAdsFailure", value:
"\n<\n\x03\x88\x03\x02\x12\bToo low.\"+\x12\x0E\n\noperations\x12\x00\x12\b\n\x06create
\x12\x0F\n\ramount_micros\n;\n\x03\xB0\x03\x02\x12\nToo short.\x1A\x02*\x00\"$\x12\x10\n
\noperations\x12\x02\b\x01\x12\b\n\x06create\x12\x06\n\x04name">]>>
So:
It would be ideal to have access to these information.
For now, pretty much everything is attached to the client for "convenience" sake.
Yet as a developer, I would not like to need a client object to build the operations: in the end its more a global value than a convenient one.
Basically I would like to be able to create an operation, use an enum, use wrappers without the client.
For instance:
# in addition of
client = ::Google::Ads::GoogleAds::GoogleAdsClient.new
client.operation(name)
# I'd like to be able to use
::Google::Ads::GoogleAds::GoogleAdsClient.operation(name, version)
# or maybe something like
proto_lookup = ::Google::Ads::GoogleAds::ProtoLookup.new(version)
proto_lookup.operation(name)
Indeed, creating an operation should not rely on some api configuration triggered during client instantiation.
One way to achieve this would be to have proto_lookup_utils
at the class level.
Another way would be to move lookup utils in an independent object.
Would you accept either move?
Hello, I wanted to know if itยดs possible to work with Batch Processing using ruby client library. I only found examples made in php, so, I'm not sure.
[2] pry(main)> c
=> #<Google::Ads::GoogleAds::GoogleAdsClient:0x00007f920438fa20
... (redacted)
>
[3] pry(main)> fs = c.service(:GoogleAdsField)
=> #<#<Class:0x00007f9204435538>:0x00007f9204434c00
@get_google_ads_field=#<Proc:0x00007f9204425070@/Users/samphippen/.gem/ruby/2.5.3/gems/google-gax-1.5.0/lib/google/gax/api_callable.rb:246>,
@google_ads_field_service_stub=
#<Google::Ads::GoogleAds::V0::Services::GoogleAdsFieldService::Stub:0x00007f9204425368
@ch=#<GRPC::Core::Channel:0x00007f92044251b0>,
@host="googleads.googleapis.com:443",
@interceptors=
#<GRPC::InterceptorRegistry:0x00007f9204425160
@interceptors=
[#<Google::Ads::GoogleAds::LoggingInterceptor:0x00007f92044354c0
@logger=
#<Logger:0x00007f920438f7a0
@default_formatter=#<Logger::Formatter:0x00007f920438f700 @datetime_format=nil>,
@formatter=nil,
@level=1,
@logdev=#<Logger::LogDevice:0x00007f920438f6b0 @dev=#<IO:<STDERR>>, @filename=nil, @mon_count=0, @mon_mutex=#<Thread::Mutex:0x00007f920438f5e8>, @mon_owner=nil, @shift_age=nil, @shift_period_suffix=nil, @shift_size=nil>,
@progname=nil>,
@options={}>]>,
@propagate_mask=nil,
@timeout=1969-12-31 18:59:59 -0500>,
@search_google_ads_fields=#<Proc:0x00007f9204424f58@/Users/samphippen/.gem/ruby/2.5.3/gems/google-gax-1.5.0/lib/google/gax/api_callable.rb:246>>
[4] pry(main)> fs.search_google_ads_fields('')
Google::Gax::RetryError: GaxError Exception occurred in retry method that was not classified as transient, caused by undefined method `customer_id' for #<Google::Ads::GoogleAds::V0::Services::SearchGoogleAdsFieldsRequest:0x00007f92043787a8>
from /Users/samphippen/.gem/ruby/2.5.3/gems/google-gax-1.5.0/lib/google/gax/api_callable.rb:369:in `rescue in block in retryable'
Caused by NoMethodError: undefined method `customer_id' for #<Google::Ads::GoogleAds::V0::Services::SearchGoogleAdsFieldsRequest:0x00007f92043787a8>
from /Users/samphippen/.gem/ruby/2.5.3/gems/google-ads-googleads-0.8.0/lib/google/ads/google_ads/logging_interceptor.rb:34:in `method_missing'
[5] pry(main)> fs.search_google_ads_fields('select * from foo')
Google::Gax::RetryError: GaxError Exception occurred in retry method that was not classified as transient, caused by undefined method `customer_id' for #<Google::Ads::GoogleAds::V0::Services::SearchGoogleAdsFieldsRequest:0x00007f920436fdd8>
from /Users/samphippen/.gem/ruby/2.5.3/gems/google-gax-1.5.0/lib/google/gax/api_callable.rb:369:in `rescue in block in retryable'
Caused by NoMethodError: undefined method `customer_id' for #<Google::Ads::GoogleAds::V0::Services::SearchGoogleAdsFieldsRequest:0x00007f920436fdd8>
from /Users/samphippen/.gem/ruby/2.5.3/gems/google-ads-googleads-0.8.0/lib/google/ads/google_ads/logging_interceptor.rb:34:in `method_missing'
[6] pry(main)>
I would have expected this to correctly dispatch a request, not try and call customer_id on a proto that doesn't have it.
Hello,
Sometimes I get this error:
GaxError Exception occurred in retry method that was not classified as transient, caused by undefined method `each' for #String:0x0000000004146118
when I try to get reports
it seems to be random.
Hello,I try to get all keywords to many Accounts but the process launch this exception:
#<Thread:[email protected]:454 run> terminated with exception (report_on_exception is true):
Traceback (most recent call last):
11: from reportsDaily.rb:454:in `block (2 levels) in KeywordReportDaily'
10: from reportsDaily.rb:476:in `threadReportkw'
9: from reportsDaily.rb:476:in `each'
8: from reportsDaily.rb:492:in `block in threadReportkw'
7: from reportsDaily.rb:492:in `count'
6: from /usr/local/rvm/gems/ruby-2.5.1/gems/google-gax-1.4.0/lib/google/gax/api_callable.rb:160:in `each'
5: from /usr/local/rvm/gems/ruby-2.5.1/gems/google-gax-1.4.0/lib/google/gax/api_callable.rb:173:in `each_page'
4: from /usr/local/rvm/gems/ruby-2.5.1/gems/google-gax-1.4.0/lib/google/gax/api_callable.rb:173:in `loop'
3: from /usr/local/rvm/gems/ruby-2.5.1/gems/google-gax-1.4.0/lib/google/gax/api_callable.rb:175:in `block in each_page'
2: from /usr/local/rvm/gems/ruby-2.5.1/gems/google-gax-1.4.0/lib/google/gax/api_callable.rb:189:in `next_page'
1: from /usr/local/rvm/gems/ruby-2.5.1/gems/google-gax-1.4.0/lib/google/gax/api_callable.rb:358:in `block in retryable'
/usr/local/rvm/gems/ruby-2.5.1/gems/google-gax-1.4.0/lib/google/gax/api_callable.rb:369:in `rescue in block in retryable': GaxError Exception occurred in retry method that was not classified as transient, caused by 13:Internal error encountered. (Google::Gax::RetryError)
Traceback (most recent call last):
11: from reportsDaily.rb:454:in `block (2 levels) in KeywordReportDaily'
10: from reportsDaily.rb:476:in `threadReportkw'
9: from reportsDaily.rb:476:in `each'
8: from reportsDaily.rb:492:in `block in threadReportkw'
7: from reportsDaily.rb:492:in `count'
6: from /usr/local/rvm/gems/ruby-2.5.1/gems/google-gax-1.4.0/lib/google/gax/api_callable.rb:160:in `each'
5: from /usr/local/rvm/gems/ruby-2.5.1/gems/google-gax-1.4.0/lib/google/gax/api_callable.rb:173:in `each_page'
4: from /usr/local/rvm/gems/ruby-2.5.1/gems/google-gax-1.4.0/lib/google/gax/api_callable.rb:173:in `loop'
3: from /usr/local/rvm/gems/ruby-2.5.1/gems/google-gax-1.4.0/lib/google/gax/api_callable.rb:175:in `block in each_page'
2: from /usr/local/rvm/gems/ruby-2.5.1/gems/google-gax-1.4.0/lib/google/gax/api_callable.rb:189:in `next_page'
1: from /usr/local/rvm/gems/ruby-2.5.1/gems/google-gax-1.4.0/lib/google/gax/api_callable.rb:358:in `block in retryable'
/usr/local/rvm/gems/ruby-2.5.1/gems/google-gax-1.4.0/lib/google/gax/api_callable.rb:369:in `rescue in block in retryable': GaxError Exception occurred in retry method that was not classified as transient, caused by 13:Internal error encountered. (Google::Gax::RetryError)
[ec2-user@ip-172-31-44-96 rbfiles]$
I get it only sometimes,
could you help me?
thanks
In resources/group_placement_view_pb.rb
the resource is generated in the Google::Ads::GoogleAds::V1::Services
namespace. However, in services/group_placement_view_service_services_pb.rb
it's referred to under the resources namespace.
There is no place in the library where the group placement view proto is defined under the resources namespace.
The README currently has this example:
campaign_service = client.service(:Campaign)
However the examples show a new syntax:
client.service.campaign
I'm in the process of creating a Documentation PR to fix that.
After the v2 update, the exception Google::Ads::GoogleAds::Errors::GoogleAdsError
never raise.
I created campaign 2042698994 and then created a draft campaign using the CampaignDraftService.MutateCampaignDrafts , the service call return me [<Google::Ads::GoogleAds::V1::Services::MutateCampaignDraftResult: resource_name: "customers/4983552381/campaignDrafts/2042698994~281474976710656">]
As per documentation this is of the format
customers/{customer_id}/campaignDrafts/{base_campaign_id}~{draft_id}
When I query campaign drafts using the draft_id=281474976710656 I get a totally unrelated draft
#<Object:0x00007f933463b748 @external_id="281474976710656", @resource_name="281474976710656", @status=:REMOVED, @draft_id=281474976710656, @base_campaign="699490231", @name="Test Campaign 50604-exp_3985", @draft_campaign="281475676200887", @has_experiment_running=false, @long_running_operation=nil>
I try to fetch account hierarchy for a managed account using a single query.
ga_service = client.service(:GoogleAds)
query = <<~QUERY
SELECT customer_client_link.client_customer, customer.descriptive_name
FROM customer_client_link
QUERY
response = ga_service.search('<MCC_ACCOUNT_ID>', query, page_size: 10)
The descriptive_name
returned is the name of the MCC account not client.
How would you do it?
Hello,
May I know what's the latest version of google-ads-ruby that still support ruby 1.8.7?
Thank you.
I believe the resources should define getters and setters for all the attributes which do the appropriate wrapper calls rather than expecting the user of the api to tediously call wrapper as in the following
payload = client.resource(:CampaignBudget)
payload.name = client.wrapper.string(name)
which should just be imho
payload.name = name
Similarly, resource and operation should take hashes as args and set the corresponding attributes
payload = client.resource(:CampaignBudget, {name: name, amount_micros: amount, delivery_method: 'ACCELERATED', explicitly_shared: true})
You'll note that I expect the setter for 'delivery_method' to know how to find its enum and lookup the value. (I'm writing our own shims to do this but would prefer to use yours)
Hi,
I m migrating 2.0.0
code to "3.2.0"
.
I am specifically trying to add a policy exemption to the payload of a keyword. Here is the code:
factories = Google::Ads::GoogleAds::Factories
keyword = factories.version_alternate_for(:resources).ad_group_criterion
operation = factories.version_alternate_for(:operations).create_resource.ad_group_criterion(keyword)
policy_violation_key = Google::Ads::GoogleAds::V1::Common::PolicyViolationKey.new(policy_name: "pharma", violating_text: "drug")
operation.exempt_policy_violation_keys.push(policy_violation_key)
# => *** Google::Protobuf::TypeError Exception: Invalid type Google::Ads::GoogleAds::V1::Common::PolicyViolationKey to assign to submessage field ''.
It worked on v2.0.0, what must I do now please? there is no relevant stacktrace and the error message is a little confusing.
Thanks in advance.
headers[:"login-customer-id"] = login_customer_id
You must add .to_s
otherwise it gives an error downstream about headers must be strings
And, you may as well cast it to int if it was passed as string in order to do the bounds check
When the refresh token is invalid, client goes into an infinite loop instead of raising exceptions:
[3] pry(main)> client.service(:Customer).list_accessible_customers
W, [2019-04-29T15:28:27.286127 #41] WARN -- : CID: N/A, Host: googleads.googleapis.com:443, Method: /google.ads.googleads.v1.services.CustomerService/ListAccessibleCustomers, IsFault: yes
I, [2019-04-29T15:28:27.286886 #41] INFO -- : Outgoing request: Headers: {"x-goog-api-client":"gl-ruby/2.6.3 gapic/1.1.1 gax/1.5.0 grpc/1.20.0","developer-token":"hidden"} Payload: {}
I, [2019-04-29T15:28:27.287015 #41] INFO -- : Incoming response (errors):
Could not parse error details due to a malformed server response trailer.
W, [2019-04-29T15:28:27.488532 #41] WARN -- : CID: N/A, Host: googleads.googleapis.com:443, Method: /google.ads.googleads.v1.services.CustomerService/ListAccessibleCustomers, IsFault: yes
I, [2019-04-29T15:28:27.488826 #41] INFO -- : Outgoing request: Headers: {"x-goog-api-client":"gl-ruby/2.6.3 gapic/1.1.1 gax/1.5.0 grpc/1.20.0","developer-token":"hidden"} Payload: {}
I, [2019-04-29T15:28:27.489125 #41] INFO -- : Incoming response (errors):
Could not parse error details due to a malformed server response trailer.
W, [2019-04-29T15:28:27.625463 #41] WARN -- : CID: N/A, Host: googleads.googleapis.com:443, Method: /google.ads.googleads.v1.services.CustomerService/ListAccessibleCustomers, IsFault: yes
I, [2019-04-29T15:28:27.625792 #41] INFO -- : Outgoing request: Headers: {"x-goog-api-client":"gl-ruby/2.6.3 gapic/1.1.1 gax/1.5.0 grpc/1.20.0","developer-token":"hidden"} Payload: {}
I, [2019-04-29T15:28:27.626775 #41] INFO -- : Incoming response (errors):
Could not parse error details due to a malformed server response trailer.
most_recent_error.status_details
can be nil. Either change Google::Gax::Grpc.deserialize_error_status_details
to return an empty list or change L55 to most_recent_error.status_details&.each
Hello, i'm trying to update an ad and i'm having some problems.
I can update an ad_group_ad perfectly but i try to update the "final_urls" field of the ad inside the ad_group_ad and it gets an error:
Field 'ad.final_urls' cannot be modified by 'UPDATE' operation.
Then, i try to use the client path of the ad but it's not defined in the "path_lookup_util.rb" file and it gets a NoMethod error:
NoMethodError: undefined method 'ad' for #<Google::Ads::GoogleAds::PathLookupUtil>
And finally, i try to define the method by myself in the gem but it gets another error:
ArgumentError: No service found with name Ad
So, it looks like the service of the Ad resource is not defined and i can't do any operations with them.
Any help? Thanks.
All our calls are currently of the form call(customer_id, something)
, the new gapic generated services take request
like objects, we'll need to codegen out a translation layer so we don't break existing users
When I tried to use keyword_plan_idea_service_client.rb to list keyword ideas, always return this error to me:
Error: 'GaxError Exception occurred in retry method that was not classified as transient, caused by 5:Requested entity was not found.'
Cause: '5:Requested entity was not found.'
Code: 5
Details: 'Requested entity was not found.'
Request-Id: 'MNH7cNiC8MpCzHokdPDu_Q'
Example:
kp_idea_service = client.service(:KeywordPlanIdea)
seed = client.resource(:UrlSeed)
seed.url = client.wrapper.string("github.com")
kp_idea_service.generate_keyword_ideas(
customer_id,
client.wrapper.string(client.path.language_constant('en_US')),
[client.wrapper.string(client.path.geo_target_constant(2076))],
client.enum(:KeywordPlanNetwork)::GOOGLE_SEARCH,
url_seed: seed
)
/home/toshi/.rvm/gems/ruby-2.6.0/gems/google-gax-1.5.0/lib/google/gax/api_callable.rb:369:in `rescue in block in retryable'
/home/toshi/.rvm/gems/ruby-2.6.0/gems/google-gax-1.5.0/lib/google/gax/api_callable.rb:358:in `block in retryable'
/home/toshi/.rvm/gems/ruby-2.6.0/gems/google-gax-1.5.0/lib/google/gax/api_callable.rb:230:in `block in create_api_call'
/home/toshi/.rvm/gems/ruby-2.6.0/gems/google-gax-1.5.0/lib/google/gax/api_callable.rb:260:in `block in create_api_call'
/home/toshi/.rvm/gems/ruby-2.6.0/gems/google-ads-googleads-1.1.1/lib/google/ads/google_ads/v1/services/keyword_plan_idea_service_client.rb:245:in `generate_keyword_ideas'
teste.rb:55:in `generate_keyword_ideas'
teste.rb:145:in `<main>'
After the v1.0 update, a query with wrong arguments should expect the next error: Google::Ads::GoogleAds::Errors::GoogleAdsError
But it never raised and, instead, it raises a GRPC::InvalidArgument
error.
Is this correct? Thanks.
When I create CampaignService without factory functions, the output of the mutation doesn't contain descriptions of request.
> client.service(:GoogleAds)
=> #<Google::Ads::GoogleAds::V1::Services::GoogleAdsServiceClient:0x00007fd00afd6d30
@google_ads_service_stub=
#<Google::Ads::GoogleAds::V1::Services::GoogleAdsService::Stub:0x00007fd00afb4bb8
@ch=#<GRPC::Core::Channel:0x00007fd00ccb1478>,
@host="googleads.googleapis.com:443",
@interceptors=#<GRPC::InterceptorRegistry:0x00007fd00afb4a00 @interceptors=[]>,
@propagate_mask=nil,
@timeout=1970-01-01 08:59:59 +0900>,
@mutate=#<Proc:0x00007fd00afb45c8@/Users/.../vendor/bundle/gems/google-gax-1.5.0/lib/google/gax/api_callable.rb:246>,
@search=#<Proc:0x00007fd00afb4758@/Users/.../vendor/bundle/gems/google-gax-1.5.0/lib/google/gax/api_callable.rb:246>>
> client.service(:GoogleAds).search(client_id, 'SELECT campaign.name FROM campaign', page_size: 1000)
=> #<Google::Gax::PagedEnumerable:0x00007fd009c80790
@func=#<Proc:0x00007fd009c7b588@/Users/.../vendor/bundle/gems/google-gax-1.5.0/lib/google/gax/api_callable.rb:353>,
@page=
#<Google::Gax::PagedEnumerable::Page:0x00007fd007897e00
@resource_field="results",
@response=
<Google::Ads::GoogleAds::V1::Services::SearchGoogleAdsResponse: results: [<Google::Ads::GoogleAds::V1::Services::GoogleAdsRow: customer: nil, campaign: <Google::Ads::GoogleAds::V1::Resources::Campaign: resource_name: "customers/...">]>
@response_page_token_field="next_page_token">,
@request=<Google::Ads::GoogleAds::V1::Services::SearchGoogleAdsRequest: customer_id: "...", query: "SELECT campaign.name FROM campaign", page_token: "", page_size: 1000, validate_only: false>,
@request_page_token_field="page_token">
On the other hand, when I do same thing with factory function, then I obtain descriptions of request in the outputs.
> client.service.google_ads
=> #<#<Class:0x00007fd00caa9388>:0x00007fd00caa9040
@google_ads_service_stub=
#<Google::Ads::GoogleAds::V1::Services::GoogleAdsService::Stub:0x00007fd00af1d740
@ch=#<GRPC::Core::Channel:0x00007fd00caa9dd8>,
@host="googleads.googleapis.com:443",
@interceptors=
#<GRPC::InterceptorRegistry:0x00007fd00af1d588
@interceptors=
[#<Google::Ads::GoogleAds::LoggingInterceptor:0x00007fd00caa9cc0
@logger=
#<ActiveSupport::Logger:0x00007fd00c9a3380
@default_formatter=#<Logger::Formatter:0x00007fd00c9a32e0 @datetime_format=nil>,
@formatter=#<ActiveSupport::Logger::SimpleFormatter:0x00007fd00ca931c8 @datetime_format=nil, @thread_key="activesupport_tagged_logging_tags:70265771170020">,
@level=0,
@local_levels=#<Concurrent::Map:0x00007fd00c9a3178 entries=0 default_proc=nil>,
@logdev=
#<Logger::LogDevice:0x00007fd00c9a3290
@dev=#<File:/Users/.../log/development.log>,
@filename=nil,
@mon_count=0,
@mon_mutex=#<Thread::Mutex:0x00007fd00c9a3218>,
@mon_owner=nil,
@shift_age=nil,
@shift_period_suffix=nil,
@shift_size=nil>,
@progname=nil>,
@options={}>]>,
@propagate_mask=nil,
@timeout=1970-01-01 08:59:59 +0900>,
@mutate=#<Proc:0x00007fd00af1d218@/Users/.../vendor/bundle/gems/google-gax-1.5.0/lib/google/gax/api_callable.rb:246>,
@search=#<Proc:0x00007fd00af1d330@/Users/.../vendor/bundle/gems/google-gax-1.5.0/lib/google/gax/api_callable.rb:246>>
> client.service.google_ads.search(client_id, 'SELECT campaign.name FROM campaign', page_size: 1000)
CID: ..., Host: googleads.googleapis.com:443, Method: /google.ads.googleads.v1.services.GoogleAdsService/Search, IsFault: no
Outgoing request: Headers: {"x-goog-api-client":"gl-ruby/2.5.5 gapic/2.4.1 gax/1.5.0 grpc/1.21.0","developer-token":"...","login-customer-id":"..."} Payload: {"customerId":"...","query":"SELECT campaign.name FROM campaign","pageSize":1000}
Incoming response: Payload: {"results":[{"campaign":{"resourceName":"customers/.../campaigns/...","name":"..."}},...
=> #<Google::Gax::PagedEnumerable:0x00007fd00c8f0f28
@func=#<Proc:0x00007fd00c8eae70@/Users/.../gax/api_callable.rb:353>,
@page=
#<Google::Gax::PagedEnumerable::Page:0x00007fd00c889238
@resource_field="results",
@response=
<Google::Ads::GoogleAds::V1::Services::SearchGoogleAdsResponse: results: [<Google::Ads::GoogleAds::V1::Services::GoogleAdsRow: customer: nil, campaign: <Google::Ads::GoogleAds::V1::Resources::Campaign: resource_name: "customers/...">]
@response_page_token_field="next_page_token">,
@request=<Google::Ads::GoogleAds::V1::Services::SearchGoogleAdsRequest: customer_id: "...", query: "SELECT campaign.name FROM campaign", page_token: "", page_size: 1000, validate_only: false>,
@request_page_token_field="page_token">
I think those changes might cause the problem. It looks like failed to insert logger.
I wanted to create a campaign experiment and as the first step I need to create a draft campaign. The document says there is CampaignDraftService but the client is missing this service
@client.service(:CampaignDraft)
=> No service found with name CampaignDraft
With google-gax
v1.5.0
This code is crashing for us:
google-ads-ruby/lib/google/ads/google_ads/logging_interceptor.rb
Lines 31 to 37 in b925f8a
When we call service.get_campaign_budget("customers/#{id1}/campaignBudgets/#{id2}")
:
Because Google::Gax::to_proto
is not returning an object that responds to customer_id
:
[7] pry(#<#<Class:0x00000000068d0300>>)> Google::Gax::to_proto({resource_name: resource_name}, Google::Ads::GoogleAds::V0::Services::GetCampaignBudgetRequest)
=> <Google::Ads::GoogleAds::V0::Services::GetCampaignBudgetRequest: resource_name: "customers/REMOVED_ID1/campaignBudgets/REMOVED_ID2">
Bundler could not find compatible versions for gem "faraday". This gem requires minimum v0.12 for faraday and I am using some other gems which require lesser version for faraday, due to which I am unable to install it in my rails application.
Thanks for the examples of OAuth Installed Application flow and OAuth Web Application Flow.
Will the ruby client library also work using the Server to Server Example listed on the Google Identity Platform?
Do you have a short example or any tips on getting that started?
I created a campaign and inserted a campaign criterion of type LOCATION = US for the it, it was performed successfully. Then I inserted a criterion of type LANGUAGE = English for it which also was performed successfully. But the original LOCATION criterion was deleted.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.