Skip to content

feat: Add UX improvements to naming templates - live preview, presets, validation#306

Merged
bokelley merged 5 commits intomainfrom
bokelley/wonderstruck-unique-name
Oct 7, 2025
Merged

feat: Add UX improvements to naming templates - live preview, presets, validation#306
bokelley merged 5 commits intomainfrom
bokelley/wonderstruck-unique-name

Conversation

@bokelley
Copy link
Collaborator

@bokelley bokelley commented Oct 7, 2025

Summary

Adds publisher-configurable GAM order/line item naming templates with comprehensive UX improvements based on agent feedback.

Problem

Publishers were getting GAM orders named "None - X packages" because we were using optional campaign_name instead of required promoted_offering. More broadly, different publishers have different naming conventions - some want dates, some want advertiser names, some want brief summaries. Hardcoding the format doesn't work for a platform.

Solution

Built a configurable naming template system with:

  • Variable substitution with fallback syntax
  • Live preview showing exact output
  • Preset templates for common use cases
  • Real-time validation
  • Comprehensive inline help

Changes

Commit 1: Core Feature (57cc4ab)

  • Database schema: Added gam_order_name_template and gam_line_item_name_template to adapter_config
  • Template engine: Variable substitution with fallback syntax ({var1|var2})
  • Smart date formatting (handles same month, different months, different years)
  • Admin UI: Basic configuration fields
  • GAM adapter: Loads templates from config and applies them

Commit 2: Better Defaults (71b3cf1)

  • Quick fix: Used promoted_offering with fallback to campaign_name
  • Prevented "None" from appearing in order names

Commit 3: UX Improvements (eeb93aa)

Based on detailed feedback from ad-tech-protocol-expert and adtech-product-expert:

1. Better Line Item Default

  • Changed from {product_name} to {order_name} - {product_name}
  • Industry standard (DV360, TTD, Amazon DSP all do this)
  • Provides campaign context in line-item reports
  • Result: "Nike Q1 Launch - Oct 7-14, 2025 - Display 300x250"

2. Preset Template Buttons
Three one-click presets:

  • 📊 Simple: {promoted_offering} - {date_range}
  • 🎯 Campaign-First: {campaign_name|promoted_offering} - {month_year}
  • 📅 Detailed: {campaign_name|promoted_offering} - {date_range} - {package_count}pkg

3. Live Preview with Sample Data

  • Real-time rendering as you type
  • Shows order name + 3 line item examples
  • Uses realistic sample: campaign_name=null, promoted_offering="Nike Shoes Q1", 3 products
  • Updates immediately on input change

4. Inline Variable Help

  • Collapsible <details> sections for each template
  • Explains every variable with examples:
    • {campaign_name} - Campaign name (optional - may be empty)
    • {promoted_offering} - What's being advertised (always present)
    • {buyer_ref} - Buyer's internal reference (optional)
    • {date_range} - Flight dates (e.g., "Oct 7-14, 2025")
    • {month_year} - Month and year (e.g., "Oct 2025")
    • {package_count} - Number of packages in order
  • Documents fallback syntax: {var1|var2} uses var1 if present, else var2
  • Non-intrusive until clicked

5. Client-Side Validation
Validates templates in real-time:

  • ✅ Empty results: "⚠️ Template produces empty name - add fallback variables"
  • ✅ Character limits: "❌ Order name too long (320 chars, max 255)"
  • ✅ Risky patterns: "💡 Tip: {campaign_name} is optional - add fallback"
  • Color-coded feedback: Red (errors), Amber (warnings), Green (success)
  • Shows character counts: "✅ Templates look good (35 chars for order, 67 chars max for line items)"

Default Templates

Order Name:

{campaign_name|promoted_offering} - {date_range}

Examples:

  • With campaign_name: "Q1 Launch - Oct 7-14, 2025"
  • Without (fallback): "Nike Shoes - Oct 7-14, 2025"

Line Item Name:

{order_name} - {product_name}

Examples:

  • "Nike Q1 Launch - Oct 7-14, 2025 - Display 300x250"
  • "Spring Promo - Mar 2025 - Video Pre-roll"

Available Variables

For Orders:

  • {campaign_name} - Optional buyer field
  • {promoted_offering} - Required (what's being advertised)
  • {buyer_ref} - Optional buyer reference
  • {date_range} - Formatted flight dates
  • {month_year} - Month-focused format
  • {package_count} - Number of packages

For Line Items:

  • {product_name} - Product/inventory name
  • {order_name} - Parent order name (for context)
  • {package_index} - Package position (1, 2, 3...)

Benefits

For Publishers

  • Control: Define your own naming conventions
  • Consistency: Templates ensure uniform naming
  • Flexibility: Supports any pattern (dates, advertisers, briefs, etc.)
  • Spec Compliant: Works with all AdCP fields (required and optional)

For Users

  • Power users: Full flexibility with custom templates and live feedback
  • Average users: Click preset button → See preview → Save (5 seconds)
  • All users: Know exactly what names will look like before committing

Testing

  • ✅ All unit tests pass
  • ✅ Pre-commit hooks pass (schema validation, linting, formatting)
  • ✅ MCP tool contract validation passes
  • ✅ AdCP spec compliance validated
  • ⚠️ One integration test fails in quick mode (database not running - unrelated to changes)

Migration

Migration ede76bc258af adds two fields:

  • gam_order_name_template (String, 500 chars, nullable)
  • gam_line_item_name_template (String, 500 chars, nullable)

Existing GAM tenants get defaults automatically.

Screenshots

Live preview with validation:

┌─────────────────────────────────────────────────┐
│ Order Name:                                     │
│ Nike Shoes Q1 - Oct 7-14, 2025                 │
├─────────────────────────────────────────────────┤
│ Line Item Names:                                │
│ 1. Nike Shoes Q1 - Oct 7-14, 2025 - Display... │
│ 2. Nike Shoes Q1 - Oct 7-14, 2025 - Video...  │
│ 3. Nike Shoes Q1 - Oct 7-14, 2025 - Native... │
├─────────────────────────────────────────────────┤
│ ✅ Templates look good (35 chars for order,    │
│    67 chars max for line items)                 │
└─────────────────────────────────────────────────┘

Follow-up Work

Phase 2 (Future):

  • Add {advertiser_name} variable (useful for multi-advertiser publishers)
  • Template presets based on publisher tier/business model
  • Import/export templates between tenants

References


🤖 Generated with Claude Code

Co-Authored-By: Claude noreply@anthropic.com

bokelley and others added 5 commits October 6, 2025 19:57
…order names

Issue: GAM adapter was creating order names like "None - 1 packages" because
it used the optional campaign_name field which could be None.

Root Cause:
- campaign_name is optional (can be None)
- promoted_offering is required by AdCP spec (always present)
- Code was using campaign_name directly without fallback

Changes:
1. google_ad_manager.py line 298: Added fallback logic
   - campaign_identifier = request.campaign_name or request.promoted_offering
   - Ensures order name is always meaningful

2. gam/managers/workflow.py lines 144, 152, 158, 199: Same fix
   - Manual workflow instructions now show correct campaign name
   - Transaction details use campaign_identifier

Result:
✅ Before: "None - 1 packages" (when campaign_name not provided)
✅ After: "Test Campaign - 1 packages" (uses promoted_offering)

This follows AdCP best practice: Use required fields for critical
operations, optional fields only as enhancements.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Problem: Publishers have different naming conventions for GAM orders.
Hardcoding format like "{promoted_offering} - {len(packages)} packages"
doesn't work for everyone. Some want dates, some want advertiser names,
some want brief summaries.

Solution: Publisher-configurable naming templates with variable substitution.

Changes:
1. Database schema (migration ede76bc258af):
   - Added gam_order_name_template to adapter_config
   - Added gam_line_item_name_template to adapter_config
   - Default: "{campaign_name|promoted_offering} - {date_range}"

2. Template system (src/adapters/gam/utils/naming.py):
   - apply_naming_template() - Variable substitution with fallbacks
   - build_order_name_context() - Extract variables from request
   - format_date_range() - Smart date formatting
   - Fallback syntax: {var1|var2} uses var1 if present, else var2

3. Admin UI (templates/tenant_settings.html):
   - New "Naming Templates" section in GAM settings
   - Configuration fields with examples and variable documentation
   - JavaScript updated to save templates

4. Backend (src/admin/blueprints/gam.py):
   - Updated configure_gam() to accept naming templates
   - Saves templates to adapter_config table

5. GAM adapter integration:
   - google_ad_manager.py: Load template from config, apply to orders
   - workflow.py: Use templates for manual order workflows

Available Variables:
- Orders: {campaign_name}, {promoted_offering}, {buyer_ref},
         {date_range}, {month_year}, {package_count}
- Line Items: {product_name}, {order_name}, {package_index}

Example Templates:
- "{campaign_name} - {month_year}" → "Q1 Launch - Oct 2025"
- "{promoted_offering} - {date_range}" → "Nike Shoes - Oct 7-14, 2025"
- "{buyer_ref|campaign_name}" → Uses buyer ref or falls back to campaign

Benefits:
- ✅ Publisher control over naming conventions
- ✅ Consistent naming across all orders
- ✅ Flexible (dates, advertiser, brief, etc.)
- ✅ Spec compliant (works with required and optional AdCP fields)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…, validation

Based on agent feedback from ad-tech-protocol-expert and adtech-product-expert.

Changes:
1. Updated line item default from "{product_name}" to "{order_name} - {product_name}"
   - Industry standard (DV360, TTD, Amazon DSP)
   - Provides campaign context in line-item reports
   - Better for performance analysis

2. Added preset template buttons:
   - 📊 Simple: "{promoted_offering} - {date_range}"
   - 🎯 Campaign-First: "{campaign_name|promoted_offering} - {month_year}"
   - 📅 Detailed: "{campaign_name|promoted_offering} - {date_range} - {package_count}pkg"

3. Added live preview with sample data:
   - Real-time template rendering
   - Shows order name and 3 line item examples
   - Updates as user types

4. Added inline variable help text:
   - Collapsible <details> sections
   - Explains what each variable means
   - Shows fallback syntax examples

5. Added client-side validation:
   - Checks for empty results
   - Validates GAM character limits (255 chars)
   - Warns about risky patterns (optional fields without fallbacks)
   - Color-coded feedback (red for errors, amber for warnings, green for success)

6. Migration update:
   - Changed default line item template to include order_name

UX Benefits:
- Power users: Full flexibility with custom templates
- Average users: Click preset button, done in 5 seconds
- All users: See exactly what names will look like before saving
- Validation catches common mistakes immediately

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Resolves Alembic 'Multiple head revisions' error in CI by merging:
- aff9ca8baa9c: allow_users_multi_tenant_access (from PR #303)
- ede76bc258af: add_naming_templates_to_adapter_config (this PR)

Both migrations branched from a7acdcb7b3d3, requiring a merge migration.
@bokelley bokelley merged commit cf5b10b into main Oct 7, 2025
8 checks passed
danf-newton pushed a commit to Newton-Research-Inc/salesagent that referenced this pull request Nov 24, 2025
…, validation (prebid#306)

* Fix: Use promoted_offering instead of optional campaign_name for GAM order names

Issue: GAM adapter was creating order names like "None - 1 packages" because
it used the optional campaign_name field which could be None.

Root Cause:
- campaign_name is optional (can be None)
- promoted_offering is required by AdCP spec (always present)
- Code was using campaign_name directly without fallback

Changes:
1. google_ad_manager.py line 298: Added fallback logic
   - campaign_identifier = request.campaign_name or request.promoted_offering
   - Ensures order name is always meaningful

2. gam/managers/workflow.py lines 144, 152, 158, 199: Same fix
   - Manual workflow instructions now show correct campaign name
   - Transaction details use campaign_identifier

Result:
✅ Before: "None - 1 packages" (when campaign_name not provided)
✅ After: "Test Campaign - 1 packages" (uses promoted_offering)

This follows AdCP best practice: Use required fields for critical
operations, optional fields only as enhancements.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* feat: Add configurable GAM order/line item naming templates

Problem: Publishers have different naming conventions for GAM orders.
Hardcoding format like "{promoted_offering} - {len(packages)} packages"
doesn't work for everyone. Some want dates, some want advertiser names,
some want brief summaries.

Solution: Publisher-configurable naming templates with variable substitution.

Changes:
1. Database schema (migration ede76bc258af):
   - Added gam_order_name_template to adapter_config
   - Added gam_line_item_name_template to adapter_config
   - Default: "{campaign_name|promoted_offering} - {date_range}"

2. Template system (src/adapters/gam/utils/naming.py):
   - apply_naming_template() - Variable substitution with fallbacks
   - build_order_name_context() - Extract variables from request
   - format_date_range() - Smart date formatting
   - Fallback syntax: {var1|var2} uses var1 if present, else var2

3. Admin UI (templates/tenant_settings.html):
   - New "Naming Templates" section in GAM settings
   - Configuration fields with examples and variable documentation
   - JavaScript updated to save templates

4. Backend (src/admin/blueprints/gam.py):
   - Updated configure_gam() to accept naming templates
   - Saves templates to adapter_config table

5. GAM adapter integration:
   - google_ad_manager.py: Load template from config, apply to orders
   - workflow.py: Use templates for manual order workflows

Available Variables:
- Orders: {campaign_name}, {promoted_offering}, {buyer_ref},
         {date_range}, {month_year}, {package_count}
- Line Items: {product_name}, {order_name}, {package_index}

Example Templates:
- "{campaign_name} - {month_year}" → "Q1 Launch - Oct 2025"
- "{promoted_offering} - {date_range}" → "Nike Shoes - Oct 7-14, 2025"
- "{buyer_ref|campaign_name}" → Uses buyer ref or falls back to campaign

Benefits:
- ✅ Publisher control over naming conventions
- ✅ Consistent naming across all orders
- ✅ Flexible (dates, advertiser, brief, etc.)
- ✅ Spec compliant (works with required and optional AdCP fields)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* feat: Add UX improvements to naming templates - live preview, presets, validation

Based on agent feedback from ad-tech-protocol-expert and adtech-product-expert.

Changes:
1. Updated line item default from "{product_name}" to "{order_name} - {product_name}"
   - Industry standard (DV360, TTD, Amazon DSP)
   - Provides campaign context in line-item reports
   - Better for performance analysis

2. Added preset template buttons:
   - 📊 Simple: "{promoted_offering} - {date_range}"
   - 🎯 Campaign-First: "{campaign_name|promoted_offering} - {month_year}"
   - 📅 Detailed: "{campaign_name|promoted_offering} - {date_range} - {package_count}pkg"

3. Added live preview with sample data:
   - Real-time template rendering
   - Shows order name and 3 line item examples
   - Updates as user types

4. Added inline variable help text:
   - Collapsible <details> sections
   - Explains what each variable means
   - Shows fallback syntax examples

5. Added client-side validation:
   - Checks for empty results
   - Validates GAM character limits (255 chars)
   - Warns about risky patterns (optional fields without fallbacks)
   - Color-coded feedback (red for errors, amber for warnings, green for success)

6. Migration update:
   - Changed default line item template to include order_name

UX Benefits:
- Power users: Full flexibility with custom templates
- Average users: Click preset button, done in 5 seconds
- All users: See exactly what names will look like before saving
- Validation catches common mistakes immediately

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* chore: Merge migration heads (multi-tenant access + naming templates)

Resolves Alembic 'Multiple head revisions' error in CI by merging:
- aff9ca8baa9c: allow_users_multi_tenant_access (from PR prebid#303)
- ede76bc258af: add_naming_templates_to_adapter_config (this PR)

Both migrations branched from a7acdcb7b3d3, requiring a merge migration.

---------

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant