creative-x-ferrero/MAPPINGS_GUIDE.md
DJP b20119b383 Add complete mapping system and automated Box.com monitoring service
Major Features:
- Complete Ferrero ↔ CreativeX mapping system with 93 brands
- Automated Box.com folder monitoring service
- Email notifications with score breakdowns
- Database integration for result storage

Mapping System (v2.0.0):
- mappings.json: 93 brand mappings, 44+ channel mappings
- core/mapping_resolver.py: Translates Ferrero codes to CreativeX format
- scripts/validate_mappings.py: Validation tool for brand/channel support
- scripts/generate_brand_mappings.py: Auto-mapping tool
- scripts/download_reports.py: Scorecard PDF download tool
- Updated scripts/upload.py: Integrated mapping validation
- Updated scripts/check_status.py: Added detailed score display with guidelines

Documentation:
- Updated README.md: Complete user guide with mapping system
- Updated STATUS.md: Production-ready status with test results
- MAPPINGS_GUIDE.md: Complete mapping documentation
- MAPPING_IMPLEMENTATION.md: Implementation summary
- BRAND_MAPPINGS_REVIEW.md: Brand mapping validation guide
- PRODUCTION_BRANDS_SUMMARY.md: Production brand catalog
- PRODUCTION_MAPPING_COMPLETE.md: Mapping completion summary

Automation Service (New):
- creativex-automation/: Complete automated Box monitoring service
- Monitors Box Ferrero-In folder (363284027140) for new files
- Automatically uploads to CreativeX
- Polls for completion (30 min intervals)
- Extracts scores and stores in PostgreSQL creativex_scores table
- Sends formatted emails to file uploader + daveporter@oliver.agency
- Moves processed files to Processed subfolder

Service Components:
- automation/box_monitor.py: Box folder monitoring with uploader detection
- automation/upload_processor.py: CreativeX upload integration
- automation/status_poller.py: CreativeX status polling
- automation/result_handler.py: Score extraction and email sending
- automation/orchestrator.py: Service coordination
- automation/processing_queue.py: JSON-based processing queue
- service.py: Main service entry point
- config.py: Service configuration loader
- requirements.txt: All dependencies
- deployment/systemd/: Systemd service unit file
- Updated shared/notifier.py: Added creativex_upload_complete and creativex_upload_failed templates

Testing:
- Supports --dry-run mode for configuration testing
- Supports --scan-once mode for Box folder testing
- Manual run mode for development/testing
- Comprehensive logging with rotation (10MB, 28 backups)

Database Integration:
- Uses existing creativex_scores table (no migrations needed)
- Compatible with existing Ferrero-Opentext workflows
- Stores full CreativeX API responses in JSONB

Email Templates:
- Matches Ferrero-Opentext styling (#9c27b0 purple for CreativeX)
- Includes score, tier, guidelines breakdown, scorecard URL
- Recipients: Box uploader + CC to daveporter@oliver.agency

Deployment:
- Runs locally for dev/testing
- Systemd service for production
- Auto-restart on failure
- Complete documentation in creativex-automation/README.md

Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
2026-01-29 09:51:16 -05:00

10 KiB

Creative X Mappings Guide

Overview

The Ferrero naming convention and Creative X API use different codes and naming for brands, channels, and markets. This mapping system bridges the two systems to enable seamless uploads.

Architecture

Ferrero Filename
       ↓
  [Filename Parser] → Extracts Ferrero codes
       ↓
  [Mapping Resolver] → Translates to Creative X format
       ↓
  [API Client] → Uploads with Creative X metadata

Files

  • mappings.json - Complete mapping tables (brands, channels, countries)
  • core/mapping_resolver.py - Python module for resolving mappings
  • scripts/upload.py - Upload script (uses mapping resolver)

Mapping Tables

1. Brand Mappings

Maps Ferrero brand codes to Creative X brand names and IDs.

Example:

{
  "NUT": {
    "creativex_name": "Nutella",
    "creativex_id": 423,
    "ferrero_name": "NUTELLA"
  },
  "RAF": {
    "creativex_name": "Rafalleo",
    "creativex_id": 422,
    "ferrero_name": "RAFFAELLO"
  }
}

Current Status:

  • Nutella (NUT)
  • Raffaello (RAF) - Note: Creative X spells it "Rafalleo"
  • 103 other Ferrero brands not yet added to Creative X

2. Channel Mappings

Maps Ferrero social media codes to Creative X channel + publisher + placement combinations.

Structure:

{
  "FERRERO_CODE": {
    "ferrero_name": "Human-readable name",
    "creativex_channel": "channel_name",
    "creativex_publisher": "publisher_name (optional)",
    "creativex_placement": "placement_name (optional)",
    "creativex_ad_format": "ad_format (optional for YouTube/DV360)"
  }
}

Examples:

Facebook (requires channel + publisher + placement)

FBS → facebook_paid / facebook / facebook_stories
IGF → instagram_paid / instagram / feed

YouTube (requires channel + publisher + ad_format)

YTB → google_ads / youtube / Bumper
YTS → google_ads / youtube / Shorts

Simple channels (only need channel name)

TIK → tiktok_paid
PIN → pinterest

Supported Channels:

Ferrero Code Creative X Channel Notes
FBS, FBF, etc. facebook_paid 15 Facebook placements
IGF, IGR, IST, etc. instagram_paid 11 Instagram placements
MSI, MSS facebook_paid 2 Messenger placements
ANC, ANI, ANR facebook_paid 3 Audience Network placements
YTB, YTI, YTS, etc. google_ads 5 YouTube ad formats
DV3 dv360 Display & YouTube
TIK tiktok_paid TikTok
SNA snapchat_paid Snapchat
PIN pinterest Pinterest
TWI twitter_paid Twitter/X
AMZ amazon_paid Amazon
GOO google_ads Generic Google

3. Country Mappings

Most country codes use standard ISO 3166-1 alpha-2 codes and map directly.

Special Cases:

  • GL = "Global" (not Greenland) - Creative X expects market_name: "Global" with no ISO code
  • CZ = Czechia (Ferrero may use "Czech Republic")
  • US = "United States of America" (not just "United States")
  • GB = "United Kingdom"
  • KR = "South Korea"

All other countries use standard ISO codes (DE, IT, FR, ES, etc.)


How It Works

1. Parsing Phase

from core.filename_parser import FerreroFilenameParser

parser = FerreroFilenameParser(data_loader)
parsed = parser.parse("NUT_GL_en_MOMENT_OLV_6S_1x1_FBS_xyz.mp4")

# Result:
{
  'brand_code': 'NUT',
  'brand_name': 'NUTELLA',
  'country_code': 'GL',
  'country_name': 'GLOBAL',
  'language_code': 'en',
  'social_media': 'FBS',
  'channel': 'FB - Stories',
  ...
}

2. Mapping Phase

from core.mapping_resolver import MappingResolver

resolver = MappingResolver('mappings.json')
creativex_payload = resolver.build_creativex_payload(parsed)

# Result:
{
  'brand_name': 'Nutella',
  'channel': 'facebook_paid',
  'publisher': 'facebook',
  'placement': 'facebook_stories',
  'market_name': 'Global',
  'language': 'en',
  'dimensions': '1x1',
  'duration': '6',
  ...
}

3. Upload Phase

api_client.create_preflight({
  'name': 'NUT_GL_en_MOMENT_OLV_6S_1x1_FBS_xyz.mp4',
  'brand_name': 'Nutella',
  'market_name': 'Global',
  'channel': 'facebook_paid',
  'publisher': 'facebook',
  'placement': 'facebook_stories',
  'language': 'en',
  'dimensions': '1x1',
  'duration': '6',
  'creatives': [
    {'source_url': 'https://s3.../file.mp4'}
  ]
})

Validation

The system validates at multiple levels:

1. Brand Validation

resolver.is_brand_supported('NUT')  # True
resolver.is_brand_supported('ROC')  # False - not in Creative X yet

2. Channel Validation

resolver.is_channel_supported('FBS')  # True
resolver.is_channel_supported('XXX')  # False - not mapped

3. Full Metadata Validation

is_valid, errors = resolver.validate_metadata_for_upload(parsed_data)
if not is_valid:
    print("Errors:", errors)

Adding New Mappings

Add a New Brand

Edit mappings.json:

{
  "brand_mappings": {
    "ROC": {
      "creativex_name": "Ferrero Rocher",
      "creativex_id": 424,
      "ferrero_name": "ROCHER"
    }
  }
}

Steps:

  1. Get Creative X brand ID from /dimensions endpoint
  2. Add mapping to mappings.json
  3. Test upload: python scripts/upload.py --dry-run test_file.mp4

Add a New Channel

Edit mappings.json:

{
  "channel_mappings": {
    "NEW_PLATFORM_CODES": {
      "NPF": {
        "ferrero_name": "New Platform - Feed",
        "creativex_channel": "new_platform_paid",
        "creativex_publisher": "new_platform",
        "creativex_placement": "feed"
      }
    }
  }
}

Steps:

  1. Query /dimensions to see Creative X channel structure
  2. Determine if channel needs publisher/placement/ad_format
  3. Add mapping following existing patterns
  4. Test validation

Common Issues & Solutions

Issue: "Brand 'XXX' is not supported in Creative X"

Cause: Brand not yet added to Creative X system

Solutions:

  1. Check if brand exists: python get_dimensions.py | grep -i brandname
  2. If exists, add mapping to mappings.json
  3. If doesn't exist, contact Creative X to add brand

Issue: "Social media code 'XXX' not mapped"

Cause: Ferrero social code not in mappings.json

Solutions:

  1. Check Creative X channels: python get_dimensions.py
  2. Identify correct channel/publisher/placement
  3. Add mapping to mappings.json

Issue: "Invalid placement for channel"

Cause: Mismatch between channel and placement

Solutions:

  1. Verify placement exists: python get_dimensions.py
  2. Check channel structure (some channels need publisher+placement, others don't)
  3. Update mapping with correct structure

Issue: "Market not found"

Cause: Country code mapping issue (usually GL = Global)

Solutions:

  1. Check if country exists: python get_dimensions.py | grep -i country
  2. For "Global" uploads, ensure GL maps to market_name="Global" (no ISO code)
  3. Update country_mappings.SPECIAL_CASES if needed

Testing Mappings

1. Dry Run Test

Test mapping without uploading:

python scripts/upload.py --dry-run /path/to/test_file.mp4

Expected output:

✓ File valid
✓ Brand: NUTELLA
✓ Market: GLOBAL
✓ Channel: FB - Stories
✓ Metadata valid
✓ Mappings valid
  → Brand: Nutella
  → Channel: facebook_paid
  → Publisher: facebook
  → Placement: facebook_stories
✓ DRY RUN: Would upload file

2. Query Available Dimensions

Check what's available in Creative X:

source venv/bin/activate
python get_dimensions.py > dimensions_output.txt

Review:

  • Available brands
  • Available channels (with publishers/placements)
  • Available markets

3. Interactive Python Test

from core.mapping_resolver import MappingResolver

resolver = MappingResolver('mappings.json')

# Test brand
brand = resolver.get_creativex_brand('NUT')
print(f"Brand: {brand}")

# Test channel
channel = resolver.get_creativex_channel_mapping('FBS')
print(f"Channel: {channel}")

# Test market
market = resolver.get_creativex_market('GL')
print(f"Market: {market}")

# List all supported
print(f"Supported brands: {resolver.get_all_supported_brands()}")
print(f"Supported channels: {resolver.get_all_supported_channels()}")

Quick Reference

Filename Format

BRAND_COUNTRY_LANG_SUBJECT_ASSETTYPE_DURATION_ASPECTRATIO_SOCIAL_hash.ext
NUT_GL_en_MOMENT_OLV_6S_1x1_FBS_xyz.mp4
│   │  │  │      │   │  │   │   └── Hash/random
│   │  │  │      │   │  │   └────── Social media code (FBS)
│   │  │  │      │   │  └────────── Aspect ratio (1x1)
│   │  │  │      │   └───────────── Duration (6S)
│   │  │  │      └───────────────── Asset type (OLV)
│   │  │  └──────────────────────── Subject (MOMENT)
│   │  └─────────────────────────── Language (en)
│   └────────────────────────────── Country (GL)
└────────────────────────────────── Brand (NUT)

Upload Workflow

1. Parse filename → Extract Ferrero codes
2. Validate file → Check format/size
3. Validate Ferrero metadata → Check against data.json
4. Validate mappings → Check brand/channel exist in Creative X
5. Get presigned URL → From Creative X API
6. Upload to S3 → Direct to S3
7. Create preflight → With mapped metadata

Support

Issues:

  • Brand not mapped → Add to brand_mappings in mappings.json
  • Channel not mapped → Add to channel_mappings in mappings.json
  • Country not found → Check country_mappings.SPECIAL_CASES

Testing:

# Test with dry run
python scripts/upload.py --dry-run file.mp4

# Check dimensions
python get_dimensions.py

# Check logs
cat data/logs/creativex_upload_*.log

Documentation:

  • Main README: README.md
  • Project status: STATUS.md
  • This guide: MAPPINGS_GUIDE.md