diff --git a/templates/add_product_gam.html b/templates/add_product_gam.html index b41ffc8b7..753ae5abc 100644 --- a/templates/add_product_gam.html +++ b/templates/add_product_gam.html @@ -850,6 +850,50 @@
Pricing Option #${index + 1}
console.error('[DEBUG] targeting-data field not found!'); } + // Debug placement data + console.log('[DEBUG] ===== PLACEMENT DEBUG START ====='); + const placementsField = document.getElementById('targeted_placement_ids'); + console.log('[DEBUG] Placements field element:', placementsField); + if (placementsField) { + const placementValue = placementsField.value; + console.log('[DEBUG] Form submission - targeted_placement_ids field value:', placementValue); + console.log('[DEBUG] Form submission - placement value type:', typeof placementValue); + console.log('[DEBUG] Form submission - placement value length:', placementValue.length); + const placementIds = placementValue.split(',').filter(Boolean); + console.log('[DEBUG] Form submission - placement IDs array:', placementIds); + console.log('[DEBUG] Form submission - placement count:', placementIds.length); + + if (placementIds.length === 0 && placementValue) { + console.warn('[DEBUG] Placement field has value but split resulted in empty array!'); + } + } else { + console.error('[DEBUG] targeted_placement_ids field not found!'); + console.error('[DEBUG] Available form fields:', Array.from(document.getElementById('product-form').elements).map(e => e.id || e.name)); + } + console.log('[DEBUG] ===== PLACEMENT DEBUG END ====='); + + // Debug ad unit data + console.log('[DEBUG] ===== AD UNIT DEBUG START ====='); + const adUnitsField = document.getElementById('targeted_ad_unit_ids'); + console.log('[DEBUG] Ad units field element:', adUnitsField); + if (adUnitsField) { + const adUnitValue = adUnitsField.value; + console.log('[DEBUG] Form submission - targeted_ad_unit_ids field value:', adUnitValue); + console.log('[DEBUG] Form submission - ad unit value type:', typeof adUnitValue); + console.log('[DEBUG] Form submission - ad unit value length:', adUnitValue.length); + const adUnitIds = adUnitValue.split(',').filter(Boolean); + console.log('[DEBUG] Form submission - ad unit IDs array:', adUnitIds); + console.log('[DEBUG] Form submission - ad unit count:', adUnitIds.length); + + if (adUnitIds.length === 0 && adUnitValue) { + console.warn('[DEBUG] Ad unit field has value but split resulted in empty array!'); + } + } else { + console.error('[DEBUG] targeted_ad_unit_ids field not found!'); + console.error('[DEBUG] Available form fields:', Array.from(document.getElementById('product-form').elements).map(e => e.id || e.name)); + } + console.log('[DEBUG] ===== AD UNIT DEBUG END ====='); + // Continue with form submission return true; } diff --git a/templates/components/targeting_selector_simple.html b/templates/components/targeting_selector_simple.html index 543ce9f3a..fd8c2a730 100644 --- a/templates/components/targeting_selector_simple.html +++ b/templates/components/targeting_selector_simple.html @@ -150,23 +150,59 @@

🎯 Custom Targeting

const existingData = document.getElementById('targeting-data').value; if (existingData && existingData !== '{}') { try { - selectedTargeting = JSON.parse(existingData).key_value_pairs || {}; + const parsedData = JSON.parse(existingData); + selectedTargeting = parsedData.key_value_pairs || {}; // Build display names for existing targeting - // Note: For existing data, we'll show the internal names until values are loaded - // This is acceptable since it's rare and will be corrected on next selection + // We need to load the values from the API to get display names window.targetingDisplayNames = {}; + + // Load display names for all existing keys + const keyLoadPromises = []; for (const keyName of Object.keys(selectedTargeting)) { const key = availableKeys.find(k => k.name === keyName); if (key) { + // Initialize display names structure window.targetingDisplayNames[keyName] = { keyDisplay: key.display_name || key.name, values: {} }; + + // Load values for this key to get display names + const promise = fetch(`{{ script_name }}/api/tenant/${tenantId}/targeting/values/${key.id}`, { + credentials: 'same-origin' + }) + .then(response => response.json()) + .then(data => { + // Map value names to display info (both name and display_name) + const values = data.values || []; + values.forEach(value => { + const valueName = value.name || value.id; + const displayName = value.display_name || valueName; + // Store both the name and display name for proper formatting + window.targetingDisplayNames[keyName].values[valueName] = { + name: valueName, + displayName: displayName + }; + }); + }) + .catch(err => { + console.warn(`Failed to load display names for key ${keyName}:`, err); + }); + + keyLoadPromises.push(promise); } } - updateDisplay(); + // Wait for all display names to load, then update display + Promise.all(keyLoadPromises).then(() => { + updateDisplay(); + }).catch(err => { + console.error('Error loading targeting display names:', err); + // Still show the targeting, just with internal names + updateDisplay(); + }); + } catch (e) { console.error('Error parsing existing targeting:', e); } @@ -200,6 +236,17 @@

🎯 Custom Targeting

availableValues[keyId] = data.values || []; + // Debug: Log the first few values to see what data we're getting + if (data.values && data.values.length > 0) { + console.log('[DEBUG] Sample targeting values received:', data.values.slice(0, 3)); + console.log('[DEBUG] First value structure:', { + id: data.values[0].id, + name: data.values[0].name, + display_name: data.values[0].display_name, + key_name: data.values[0].key_name + }); + } + // Sort values alphabetically by display name const sortedValues = [...data.values].sort((a, b) => { const nameA = (a.display_name || a.name).toLowerCase(); @@ -222,15 +269,34 @@

🎯 Custom Targeting

const valueName = value.name || value.id; const displayName = value.display_name || ''; + // Debug for first few values + if (sortedValues.indexOf(value) < 3) { + console.log(`[DEBUG] Value ${sortedValues.indexOf(value)}:`, { + valueName, + displayName, + 'displayName !== valueName': displayName !== valueName, + 'displayName.match(/^\\d+$/)': displayName ? displayName.match(/^\d+$/) : null + }); + } + // If display_name exists and is different from name, show both if (displayName && displayName !== valueName && !displayName.match(/^\d+$/)) { - option.textContent = `${valueName} - ${displayName}`; + option.textContent = `${displayName} (${valueName})`; + if (sortedValues.indexOf(value) < 3) { + console.log(`[DEBUG] Using format: "${displayName} (${valueName})"`); + } } else if (displayName && !displayName.match(/^\d+$/)) { // Display name is meaningful (not just a number), use it option.textContent = displayName; + if (sortedValues.indexOf(value) < 3) { + console.log(`[DEBUG] Using display name only: "${displayName}"`); + } } else { // Fallback to name option.textContent = valueName; + if (sortedValues.indexOf(value) < 3) { + console.log(`[DEBUG] Using name only (fallback): "${valueName}"`); + } } option.dataset.keyId = keyId; @@ -274,7 +340,11 @@

🎯 Custom Targeting

values: {} }; } - window.targetingDisplayNames[keyName].values[valueName] = valueDisplayName; + // Store both name and display name for proper formatting + window.targetingDisplayNames[keyName].values[valueName] = { + name: valueName, + displayName: valueDisplayName + }; // Add value if not already present (using internal name for API) if (!selectedTargeting[keyName].includes(valueName)) { @@ -301,8 +371,25 @@

🎯 Custom Targeting

const keyDisplay = window.targetingDisplayNames?.[key]?.keyDisplay || key; values.forEach(value => { - // Get display name for value (fallback to internal name if not found) - const valueDisplay = window.targetingDisplayNames?.[key]?.values?.[value] || value; + // Get display info for value (can be object with name+displayName, or just a string) + const valueInfo = window.targetingDisplayNames?.[key]?.values?.[value]; + let valueDisplay; + + if (valueInfo && typeof valueInfo === 'object') { + // New format: object with name and displayName + const name = valueInfo.name || value; + const displayName = valueInfo.displayName || name; + + // Format as "Display Name (ID)" if they're different, otherwise just show one + if (displayName && displayName !== name && !displayName.match(/^\d+$/)) { + valueDisplay = `${displayName} (${name})`; + } else { + valueDisplay = displayName || name; + } + } else { + // Legacy format: plain string or missing + valueDisplay = valueInfo || value; + } html += ` diff --git a/templates/edit_product.html b/templates/edit_product.html index 3bafdb9e2..f3c0b220d 100644 --- a/templates/edit_product.html +++ b/templates/edit_product.html @@ -10,7 +10,7 @@

Edit Product

{{ error }}
{% endif %} -
+
@@ -141,6 +141,29 @@