Skip to content

Add incentives examples - #554

Open
dorasun wants to merge 9 commits into
mainfrom
add_incentives_example
Open

dorasun wants to merge 9 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_incentives.rb
Comment thread examples/incentives/fetch_incentives.rb
Comment thread examples/incentives/fetch_incentives.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 Outdated
Comment thread examples/incentives/fetch_incentive.rb Outdated
Comment thread examples/incentives/fetch_incentive.rb
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
Raibaz
Raibaz previously approved these changes Oct 7, 2026
Comment thread examples/incentives/fetch_incentive.rb Outdated
Comment thread examples/incentives/fetch_incentive.rb Outdated
Comment thread examples/incentives/fetch_incentive.rb Outdated
Comment thread examples/incentives/apply_incentive.rb
- Add shebang and Encoding header
- Remove trailing whitespace after .compact
- Surface consolidated terms and conditions URL when present in fetch_incentive
- Validate against empty email string in CLI options
- Add fallback confirmation message when incentive applied without coupon code or creation time

Change-Id: I5a0ed0cd2a2ef3744b28c6f83a47a12dfd2cb24d
@@ -0,0 +1,168 @@
#!/usr/bin/env ruby

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.

  1. DevSite filename alignment (fetch_incentives.rb): The DevSite Incentives guide (docs/billing/incentives.md) and sample page (samples/fetch-incentives.md) reference code_example_id='incentives/fetch_incentives' (plural, matching fetch_incentives.py in Python, FetchIncentives.java in Java, and FetchIncentives.cs in .NET), which resolves to examples/incentives/fetch_incentives.rb. Consider renaming this file to examples/incentives/fetch_incentives.rb so DevSite snippet inclusion works out of the box without custom path overrides.
  2. Executable file mode (100755) & header: Since #!/usr/bin/env ruby and Usage: %s [options] were added for standalone script execution, please chmod +x (100755) this file (currently 100644). Also, # Encoding: utf-8 on line 2 can be removed since UTF-8 is the default source encoding in Ruby 2.0+.

Comment thread examples/incentives/fetch_incentive.rb Outdated
response = client.service.incentive.fetch_incentive(request_args)

# Processes the response.
if response.incentive_offer.nil?

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.

When no incentive is available for a user, the API returns a populated IncentiveOffer with offer_type == :NO_INCENTIVE and cyo_incentives unset (nil). Currently, that case skips this nil? check and falls into the else branch on line 58 (printing 'Incentive offer is not a CHOOSE_YOUR_OWN_INCENTIVE type...').

Checking for :NO_INCENTIVE here handles empty offers accurately (and allows removing the redundant &. on line 49):

Suggested change
if response.incentive_offer.nil?
if response.incentive_offer.nil? || response.incentive_offer.offer_type == :NO_INCENTIVE

Comment thread examples/incentives/fetch_incentive.rb Outdated
parser.parse!

# Check if required parameters are present.
if options[:email].to_s.empty? || 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.

Since fetch_incentive strips whitespace on line 32 (email.to_s.strip), using .strip.empty? here ensures whitespace-only input (e.g., -E " ") is caught during CLI validation rather than sending an empty email: "" to the API:

Suggested change
if options[:email].to_s.empty? || options[:email] == 'INSERT_EMAIL_HERE'
if options[:email].to_s.strip.empty? || options[:email] == 'INSERT_EMAIL_HERE'

@@ -0,0 +1,138 @@
#!/usr/bin/env ruby

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.

Since #!/usr/bin/env ruby and Usage: %s [options] are used for standalone execution, please chmod +x (100755) this file (currently committed with mode 100644). Also, # Encoding: utf-8 on line 2 is redundant in Ruby 2.0+ and can be removed.

Comment thread examples/incentives/apply_incentive.rb Outdated
# Issues the request.
request_args = {
customer_id: customer_id.to_s.tr('-', ''),
selected_incentive_id: incentive_id&.to_i,

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.

If apply_incentive is called programmatically with a non-numeric string (such as an unreplaced placeholder 'INSERT_INCENTIVE_ID_HERE'), incentive_id&.to_i silently coerces it to 0 (selected_incentive_id: 0). Using Integer(incentive_id) when incentive_id is present fails fast with an ArgumentError on invalid input:

Suggested change
selected_incentive_id: incentive_id&.to_i,
selected_incentive_id: incentive_id ? Integer(incentive_id) : nil,

Comment thread examples/incentives/apply_incentive.rb Outdated
exit 1
end

if options[:country_code].to_s.empty?

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.

Use .strip.empty? (and strip country_code in request_args on line 38) to guard against whitespace-only --country-code values:

Suggested change
if options[:country_code].to_s.empty?
if options[:country_code].to_s.strip.empty?

…ssions, NO_INCENTIVE handling, and validation

Change-Id: I3fc292a3b6a8f3180c12ede0f1e7982e32179b38
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