-
Notifications
You must be signed in to change notification settings - Fork 13
fix: ad unit format button, targeting selector crash, and service account auth #723
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The 'Select All Matching' button was not appearing after selecting ad units because applyInventorySelection() was calling extractSizesFromInventory() without awaiting it. Since extractSizesFromInventory() is async, it was returning immediately before completing, so updateFormatMatchIndicators() never ran to show the button. Fix: Make applyInventorySelection() async and await the call to extractSizesFromInventory(), ensuring size extraction and format matching complete before the function returns. Fixes regression introduced in #720 where dynamic products feature was added.
When the API returns an error (e.g., 400 status), data.values can be null/undefined, causing 'TypeError: Spread syntax requires ...iterable not be null or undefined'. Changes: - Check response.ok before processing - Validate data.values exists and is an array before spreading - Show clear error messages to user instead of cryptic console errors - Add temporary error notification that auto-dismisses after 5 seconds Fixes the error seen in production when loading custom targeting values.
Split generic 'GAM not configured' 400 error into specific messages: - No adapter configured - GAM network code not configured - GAM authentication not configured (with helpful hint) This will help users understand exactly what's missing when they see the 400 error in production, making it easier to diagnose and fix the root cause instead of just handling the error gracefully.
Add detailed logging to help identify which specific configuration check is failing when the endpoint returns 400. Logs: - Request details (tenant_id, key_id) - Adapter config existence - Network code and refresh token status This will help diagnose the production issue where GAM works for other operations but fails for targeting values endpoint.
The endpoint only checked for OAuth refresh tokens, causing 400 errors for tenants using service account authentication (like 'weather' tenant). Changes: - Check for EITHER refresh token OR service account JSON - Create appropriate GAM client based on auth method: - Service account: Write JSON to temp file, create credentials, cleanup - OAuth: Use existing refresh token flow - Add logging to show which auth method is being used This matches the pattern used in background_sync_service.py which already supports both auth methods. Fixes the 400 error at https://sales-agent.scope3.com/admin/tenant/weather/products/add
…t auth Completed comprehensive audit of all files creating GAM clients to ensure they support BOTH OAuth refresh tokens AND service account authentication. ## Audit Results - ✅ All production endpoints support both auth methods - ✅ OAuth-only endpoints are intentional (setup/testing in api.py, gam.py) - ✅ 1 issue found and fixed: inventory.py:get_targeting_values() (commit 8cc6c7e) ## Prevention: New Pre-commit Hook Created `.pre-commit-hooks/check-gam-auth-support.py` to catch this pattern: - Detects new code creating GAM clients - Ensures they check for BOTH auth methods - Allows exceptions for setup/testing endpoints - Provides helpful error messages with examples ## Files Audited - src/services/background_sync_service.py ✅ (supports both) - src/adapters/gam/auth.py ✅ (supports both via GAMAuthManager) - src/adapters/gam/client.py ✅ (uses GAMAuthManager) - src/admin/blueprints/gam.py ✅ (supports both) - src/admin/blueprints/inventory.py ✅ (fixed in this PR) - src/admin/blueprints/api.py⚠️ (OAuth-only by design) - src/adapters/gam/utils/health_check.py ✅ (service account only) See AUDIT_RESULTS.md for full details.
The test was expecting 'GAM not configured' but we improved the error message to be more specific: 'No adapter configured for this tenant'. This fixes the failing CI test.
This was a temporary analysis document and doesn't need to be in the repo.
bokelley
added a commit
that referenced
this pull request
Nov 11, 2025
The targeting values endpoint was failing with 500 error for tenants using service account authentication because we were passing raw google.oauth2.service_account.Credentials directly to AdManagerClient. The googleads library requires credentials to be wrapped in oauth2.GoogleCredentialsClient to provide the CreateHttpHeader() method that the GAM API client expects. Error: AttributeError: 'Credentials' object has no attribute 'CreateHttpHeader' Fix: Add oauth2.GoogleCredentialsClient(credentials) wrapper, matching the pattern used in: - src/services/background_sync_service.py - src/adapters/gam/auth.py - src/adapters/gam/utils/health_check.py - src/admin/blueprints/gam.py This was missed in PR #723 which added service account support to this endpoint. Fixes: https://sales-agent.scope3.com/admin/api/tenant/weather/targeting/values/289457 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
bokelley
added a commit
that referenced
this pull request
Nov 11, 2025
) The targeting values endpoint was failing with 500 error for tenants using service account authentication because we were passing raw google.oauth2.service_account.Credentials directly to AdManagerClient. The googleads library requires credentials to be wrapped in oauth2.GoogleCredentialsClient to provide the CreateHttpHeader() method that the GAM API client expects. Error: AttributeError: 'Credentials' object has no attribute 'CreateHttpHeader' Fix: Add oauth2.GoogleCredentialsClient(credentials) wrapper, matching the pattern used in: - src/services/background_sync_service.py - src/adapters/gam/auth.py - src/adapters/gam/utils/health_check.py - src/admin/blueprints/gam.py This was missed in PR #723 which added service account support to this endpoint. Fixes: https://sales-agent.scope3.com/admin/api/tenant/weather/targeting/values/289457 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com>
danf-newton
pushed a commit
to Newton-Research-Inc/salesagent
that referenced
this pull request
Nov 24, 2025
…ount auth (adcontextprotocol#723) * fix: await extractSizesFromInventory in applyInventorySelection The 'Select All Matching' button was not appearing after selecting ad units because applyInventorySelection() was calling extractSizesFromInventory() without awaiting it. Since extractSizesFromInventory() is async, it was returning immediately before completing, so updateFormatMatchIndicators() never ran to show the button. Fix: Make applyInventorySelection() async and await the call to extractSizesFromInventory(), ensuring size extraction and format matching complete before the function returns. Fixes regression introduced in adcontextprotocol#720 where dynamic products feature was added. * fix: handle null/undefined values in targeting selector When the API returns an error (e.g., 400 status), data.values can be null/undefined, causing 'TypeError: Spread syntax requires ...iterable not be null or undefined'. Changes: - Check response.ok before processing - Validate data.values exists and is an array before spreading - Show clear error messages to user instead of cryptic console errors - Add temporary error notification that auto-dismisses after 5 seconds Fixes the error seen in production when loading custom targeting values. * fix: improve error messages for targeting values API endpoint Split generic 'GAM not configured' 400 error into specific messages: - No adapter configured - GAM network code not configured - GAM authentication not configured (with helpful hint) This will help users understand exactly what's missing when they see the 400 error in production, making it easier to diagnose and fix the root cause instead of just handling the error gracefully. * debug: add logging to diagnose targeting values 400 error Add detailed logging to help identify which specific configuration check is failing when the endpoint returns 400. Logs: - Request details (tenant_id, key_id) - Adapter config existence - Network code and refresh token status This will help diagnose the production issue where GAM works for other operations but fails for targeting values endpoint. * fix: support service account authentication in targeting values endpoint The endpoint only checked for OAuth refresh tokens, causing 400 errors for tenants using service account authentication (like 'weather' tenant). Changes: - Check for EITHER refresh token OR service account JSON - Create appropriate GAM client based on auth method: - Service account: Write JSON to temp file, create credentials, cleanup - OAuth: Use existing refresh token flow - Add logging to show which auth method is being used This matches the pattern used in background_sync_service.py which already supports both auth methods. Fixes the 400 error at https://sales-agent.scope3.com/admin/tenant/weather/products/add * audit: ensure all GAM endpoints support both OAuth and service account auth Completed comprehensive audit of all files creating GAM clients to ensure they support BOTH OAuth refresh tokens AND service account authentication. ## Audit Results - ✅ All production endpoints support both auth methods - ✅ OAuth-only endpoints are intentional (setup/testing in api.py, gam.py) - ✅ 1 issue found and fixed: inventory.py:get_targeting_values() (commit 8cc6c7e) ## Prevention: New Pre-commit Hook Created `.pre-commit-hooks/check-gam-auth-support.py` to catch this pattern: - Detects new code creating GAM clients - Ensures they check for BOTH auth methods - Allows exceptions for setup/testing endpoints - Provides helpful error messages with examples ## Files Audited - src/services/background_sync_service.py ✅ (supports both) - src/adapters/gam/auth.py ✅ (supports both via GAMAuthManager) - src/adapters/gam/client.py ✅ (uses GAMAuthManager) - src/admin/blueprints/gam.py ✅ (supports both) - src/admin/blueprints/inventory.py ✅ (fixed in this PR) - src/admin/blueprints/api.py⚠️ (OAuth-only by design) - src/adapters/gam/utils/health_check.py ✅ (service account only) See AUDIT_RESULTS.md for full details. * test: update targeting values test to match new error message The test was expecting 'GAM not configured' but we improved the error message to be more specific: 'No adapter configured for this tenant'. This fixes the failing CI test. * chore: remove audit results file This was a temporary analysis document and doesn't need to be in the repo.
danf-newton
pushed a commit
to Newton-Research-Inc/salesagent
that referenced
this pull request
Nov 24, 2025
…dcontextprotocol#727) The targeting values endpoint was failing with 500 error for tenants using service account authentication because we were passing raw google.oauth2.service_account.Credentials directly to AdManagerClient. The googleads library requires credentials to be wrapped in oauth2.GoogleCredentialsClient to provide the CreateHttpHeader() method that the GAM API client expects. Error: AttributeError: 'Credentials' object has no attribute 'CreateHttpHeader' Fix: Add oauth2.GoogleCredentialsClient(credentials) wrapper, matching the pattern used in: - src/services/background_sync_service.py - src/adapters/gam/auth.py - src/adapters/gam/utils/health_check.py - src/admin/blueprints/gam.py This was missed in PR adcontextprotocol#723 which added service account support to this endpoint. Fixes: https://sales-agent.scope3.com/admin/api/tenant/weather/targeting/values/289457 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem 1: Select All Matching Button Not Appearing
The 'Select All Matching' button was not appearing after selecting ad units in the GAM product form.
Root Cause
applyInventorySelection()was callingextractSizesFromInventory()without awaiting it. SinceextractSizesFromInventory()is async, it was returning immediately before completing, soupdateFormatMatchIndicators()never ran to show the button.Solution
applyInventorySelection()asyncawaitbefore callingextractSizesFromInventory()Problem 2: Targeting Selector Crashes on API Error
When loading custom targeting values fails (e.g., 400 error), the page shows:
TypeError: Spread syntax requires ...iterable not be null or undefinedRoot Cause
The code was using spread syntax on
data.valueswithout checking if it exists first. When the API returns an error,data.valuesis null/undefined.Solution
response.okbefore processing responsedata.valuesexists and is an array before spreadingProblem 3: Targeting Values 400 Error for Service Account Tenants ⭐
The targeting values endpoint returned 400 errors for tenants using service account authentication (like 'weather' tenant), even though GAM was properly configured.
Root Cause
The endpoint only checked for OAuth refresh tokens (
gam_refresh_token), completely ignoring service account authentication (gam_service_account_json). This caused 400 errors for any tenant using service account auth.Solution
background_sync_service.pyProblem 4: Generic Error Messages
The targeting values endpoint returned generic "GAM not configured" 400 error.
Solution
Split into specific error messages:
Audit & Prevention ⭐
Completed comprehensive audit of ALL endpoints creating GAM clients:
Audit Results
New Pre-commit Hook
Created
.pre-commit-hooks/check-gam-auth-support.py:Testing
Related