Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions templates/add_product_gam.html
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,50 @@ <h5 style="margin: 0;">Pricing Option #${index + 1}</h5>
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;
}
Expand Down
103 changes: 95 additions & 8 deletions templates/components/targeting_selector_simple.html
Original file line number Diff line number Diff line change
Expand Up @@ -150,23 +150,59 @@ <h4>🎯 Custom Targeting</h4>
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);
}
Expand Down Expand Up @@ -200,6 +236,17 @@ <h4>🎯 Custom Targeting</h4>

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();
Expand All @@ -222,15 +269,34 @@ <h4>🎯 Custom Targeting</h4>
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;
Expand Down Expand Up @@ -274,7 +340,11 @@ <h4>🎯 Custom Targeting</h4>
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)) {
Expand All @@ -301,8 +371,25 @@ <h4>🎯 Custom Targeting</h4>
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 += `
<span class="selected-item">
Expand Down
25 changes: 24 additions & 1 deletion templates/edit_product.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ <h2>Edit Product</h2>
<div class="alert alert-error">{{ error }}</div>
{% endif %}

<form method="POST">
<form method="POST" onsubmit="debugFormSubmission(event)">
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem;">
<div class="form-group">
<label for="name">Product Name *</label>
Expand Down Expand Up @@ -141,6 +141,29 @@ <h3 style="margin-top: 2rem;">
</div>

<script>
// Debug form submission to diagnose targeting persistence issue
function debugFormSubmission(event) {
// Log all form data for debugging
const targetingField = document.getElementById('targeting-data');
if (targetingField) {
console.log('[DEBUG] Form submission - targeting_template field value:', targetingField.value);
try {
const targetingData = JSON.parse(targetingField.value);
console.log('[DEBUG] Form submission - parsed targeting data:', targetingData);
if (targetingData.key_value_pairs) {
console.log('[DEBUG] Form submission - key_value_pairs:', targetingData.key_value_pairs);
}
} catch (e) {
console.error('[DEBUG] Failed to parse targeting data:', e);
}
} else {
console.error('[DEBUG] targeting-data field not found!');
}

// Let form submit normally
return true;
}

function updatePricingFields() {
const deliveryType = document.getElementById('delivery_type').value;
const cpmGroup = document.getElementById('cpm-group');
Expand Down