Skip to content

Add incentives examples - #554

Open
dorasun wants to merge 7 commits into
mainfrom
add_incentives_example
Open

dorasun wants to merge 7 commits into
mainfrom
add_incentives_example

Conversation

@dorasun

@dorasun dorasun commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Change-Id: I57fa8a776fb8a1cbd43f6c1d3a1a71c3c63bdd19

Change-Id: I57fa8a776fb8a1cbd43f6c1d3a1a71c3c63bdd19
@dorasun
dorasun requested a review from a team as a code owner July 15, 2026 18:19
@dorasun
dorasun requested review from Raibaz and sundquist July 15, 2026 18:19
Raibaz
Raibaz previously approved these changes Jul 16, 2026
Change-Id: I2f4db5b40ddc0494f631b62d60b6992f786cbf57
Raibaz
Raibaz previously approved these changes Jul 17, 2026
@dorasun
dorasun requested a review from bobhancockg July 17, 2026 19:32
@bobhancockg

Copy link
Copy Markdown
Contributor

Code Vetting & Review Recommendations

Overall, the implementation for adding incentive examples (apply_incentive.rb and fetch_incentive.rb) is well-structured. Below are recommended improvements to align with google-ads-ruby repository standards, fix documentation indexing tags, ensure type safety, and standardize monetary formatting.


1. examples/incentives/apply_incentive.rb

  • Default Parameter Value: Add country_code = nil to the method signature so calling apply_incentive(customer_id, incentive_id) programmatically works without explicitly passing nil:
    def apply_incentive(customer_id, incentive_id, country_code = nil)
  • Type Safety for selected_incentive_id: Explicitly call .to_i on incentive_id when constructing request_args for protobuf field type safety (int64):
    request_args = {
      customer_id: customer_id,
      selected_incentive_id: incentive_id.to_i
    }
  • CLI Default Initializers & Validation: Initialize options[:incentive_id] = 'INSERT_INCENTIVE_ID_HERE' at the top of if __FILE__ == $0 to match the doc comments, and update argument validation accordingly:
    options[:customer_id] = 'INSERT_CUSTOMER_ID_HERE'
    options[:incentive_id] = 'INSERT_INCENTIVE_ID_HERE'
    if options[:customer_id].nil? ||
        options[:customer_id] == 'INSERT_CUSTOMER_ID_HERE' ||
        options[:incentive_id].nil? ||
        options[:incentive_id] == 'INSERT_INCENTIVE_ID_HERE'
      puts 'Missing required arguments. See usage:'
      puts 'Customer ID and Incentive ID are required.'
      exit 1
    end

2. examples/incentives/fetch_incentive.rb

  • Documentation Region Tags: Add # [START fetch_incentive] and # [END fetch_incentive] region tags around the main method so Google Developers documentation (devsite) can automatically index the code snippet.
  • Standardize Currency Formatting in format_money: Simplify calculation to cleanly format zero, fractional, and negative currency values with standard 2 decimal places:
    def format_money(money)
      return 'N/A' if money.nil?
    
      amount = money.units.to_f + (money.nanos.to_f / 1_000_000_000.0)
      sprintf('%.2f %s', amount, money.currency_code)
    end
  • CLI Option Placeholder & Check: Initialize options[:email] = 'INSERT_EMAIL_HERE' and validate against INSERT_EMAIL_HERE in if __FILE__ == $0.

Comment thread examples/incentives/apply_incentive.rb
Change-Id: I19de34550a54efaa8095b503bd5e8c449930e9d4
Comment thread examples/incentives/apply_incentive.rb
Comment thread examples/incentives/apply_incentive.rb Outdated
Comment thread examples/incentives/fetch_incentive.rb
Comment thread examples/incentives/fetch_incentive.rb
Comment thread examples/incentives/fetch_incentive.rb
Change-Id: I4f3b19fe5ace2a6d88f7f0c3b90906f97b0d454b
@dorasun
dorasun removed the request for review from sundquist August 14, 2026 20:33
@dorasun
dorasun requested a review from bobhancockg August 25, 2026 21:37

@bobhancockg bobhancockg left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, the implementation for adding incentive examples is well-structured and incorporates previous feedback nicely. Here are a few remaining recommendations and optimizations before merging:

  1. examples/incentives/apply_incentive.rb:

    • Clean up redundant request_args[:country_code] = country_code if country_code duplicate assignment on line 36.
  2. examples/incentives/fetch_incentive.rb:

    • Update request field name from type: :ACQUISITION to incentive_type: :ACQUISITION to match current Google Ads API protobuf definitions (v24+) and avoid runtime ArgumentError.
    • Provide default nil arguments in def fetch_incentive(email, language_code = nil, country_code = nil) and construct request args using .compact.
    • Fix missing whitespace in string continuation on lines 51-52 ("type." \ "Non-CYO" -> "type.Non-CYO").
    • Defensively format monetary currency strings against empty protobuf defaults ("").

Comment thread examples/incentives/apply_incentive.rb
Comment thread examples/incentives/fetch_incentive.rb Outdated
Comment thread examples/incentives/fetch_incentive.rb Outdated
Comment thread examples/incentives/fetch_incentive.rb Outdated
Change-Id: I6dfd7bc56bafdf1910e5e35209600f3bc52a6e84
@dorasun
dorasun requested a review from bobhancockg September 15, 2026 16:11
@bobhancockg

Copy link
Copy Markdown
Contributor

Updated the PR with the following optimizations:

  • Parameter Defaults & API Alignment:
    • : Defaulted country_code to 'US' (required by API proto schema) rather than nil to avoid INVALID_ARGUMENT when omitted.
    • : Provided default values (language_code = 'en', country_code = 'US') matching API proto defaults.
  • Defensive Protobuf Traversal:
    • Used incentive_id&.to_i to prevent coercing nil to 0.
    • Added safe navigation (response.incentive_offer&.cyo_incentives).
    • Added !field.to_s.empty? checks for protobuf strings before output.
    • Improved requirement fallback message when spend requirement is absent.
    • Cleaned up format_money currency formatting.
  • Documentation / Code Snippet Tags:
    • Extended [START fetch_incentive] / [END fetch_incentive] scope to encompass helper functions (print_incentive_details, format_requirement, format_money) so extracted DevSite snippets are complete and runnable.
  • Diagnostics & Error Reporting:
    • Surfaced e.request_id in stderr when catching GoogleAdsError across both scripts.
    • Standardized CLI parameter validation to report the exact missing flag with OptionParser usage banner.

@Raibaz
Raibaz self-requested a review October 7, 2026 15:44
# Passing :ACQUISITION as the symbol representation of the IncentiveType enum.
incentive_type: :ACQUISITION
}.compact

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style / Formatting: Trailing whitespace on line 36 after .compact.


# If the offer type is CHOOSE_YOUR_OWN_INCENTIVE, there will be 3 incentives in the
# response. At the time this example was written, all incentive offers are CYO incentive offers.
if response.incentive_offer&.cyo_incentives

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enhancement (API Coverage): The IncentiveOffer message can also contain consolidated_terms_and_conditions_url (combining terms across all CYO incentive offers). Consider printing it when present:

  if !response.incentive_offer.consolidated_terms_and_conditions_url.to_s.empty?
    puts "Consolidated terms and conditions: '#{response.incentive_offer.consolidated_terms_and_conditions_url}'"
  end

parser.parse!

# Check if required parameters are present.
if options[:email].nil? || options[:email] == 'INSERT_EMAIL_HERE'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defensive validation: Consider checking options[:email].to_s.empty? instead of just options[:email].nil? (consistent with --country-code in apply_incentive.rb line 114):

  if options[:email].to_s.empty? || options[:email] == 'INSERT_EMAIL_HERE'
    puts "Missing required argument: --email (-E) is required.\n\n"
    puts parser
    exit 1
  end

This defensively catches empty string inputs (e.g. -E "").

if !response.coupon_code.to_s.empty?
puts "Applied incentive with coupon code '#{response.coupon_code}'."
end
end

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UX / Output: If the API returns a response where both creation_time and coupon_code happen to be empty, the method currently completes silently with no output. Consider adding a fallback confirmation if neither is printed:

  if !response.creation_time.to_s.empty?
    puts "Incentive was created at '#{response.creation_time}'."
  end
  if !response.coupon_code.to_s.empty?
    puts "Applied incentive with coupon code '#{response.coupon_code}'."
  end
  if response.creation_time.to_s.empty? && response.coupon_code.to_s.empty?
    puts "Incentive applied successfully."
  end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants