Extract & Export Qualtrics Dashboard Data Field Mappings - Complete Guide

Why Extract & Export Field Mappings?

If you work with Qualtrics Dashboard Data, you know that managing field mappings across multiple data sources can be challenging. Manually documenting which fields are mapped to which sources is time-consuming and error-prone.

This guide provides a simple browser-based method to automatically extract all your field mappings in seconds:

How to Extract Your Field Mappings

This is the fastest method and works directly in your browser while viewing the Qualtrics Dashboard Data page.

Watch the 30-Second Demo

1

Navigate to Dashboard Data

In Qualtrics, go to your Dashboard and navigate to:
Settings → Dashboard Data

Make sure the field mapping grid is visible on your screen.

2

Open Browser Console

Right-click on the first field mapping row in the Dashboard Data grid (where you see "Date", "Text Set", etc.)

Select "Inspect" or "Inspect Element" from the menu

In the developer tools that appear, click on the "Console" tab

Why this way? Right-clicking directly on a field ensures the DOM elements are loaded in the inspector, making the extraction more reliable.
3

Copy and Run the Script

Copy the script below by clicking the "Copy Script" button:

/**
 * Qualtrics Dashboard Field Extractor - v2.2
 * Extracts Field Type, Field Name, and ALL Data Source Mappings
 * Developed by Pirai AI — piraiai.com
 * Last updated: February 15, 2026
*/

(function() {
    console.log('=== Qualtrics Field Extractor v2.2 DEBUG ===');
    console.log('⚠️  IMPORTANT: Expand all Measure Groups before running!');
    console.log('⚠️  Click the arrow next to group fields to expand them.\n');
    
    function getDataSourceNames() {
        const sourceNames = [];
        const sourceContainers = document.querySelectorAll('.source-menu-container');
        
        console.log(`Found ${sourceContainers.length} source containers`);
        
        sourceContainers.forEach((container, index) => {
            try {
                const labelContainer = container.querySelector('.source-label-container');
                if (labelContainer) {
                    const sourceName = labelContainer.textContent.trim();
                    sourceNames.push({
                        index: index,
                        name: sourceName
                    });
                    console.log(`Source ${index + 1}: ${sourceName}`);
                }
            } catch (error) {
                console.warn(`Error getting source name ${index}:`, error);
                sourceNames.push({
                    index: index,
                    name: `Source ${index + 1}`
                });
            }
        });
        
        return sourceNames;
    }
    
    function extractFieldData() {
        const fields = [];
        const dataSources = getDataSourceNames();
        
        console.log(`\nData Sources Found: ${dataSources.length}`);
        dataSources.forEach(ds => console.log(`  - ${ds.name}`));
        
        // Get ALL li elements, including those nested in groups
        const allListItems = document.querySelectorAll('li.grid-field-info, li.ng-scope[grid-row]');
        
        console.log(`\nFound ${allListItems.length} total list items\n`);
        
        let processedCount = 0;
        
        allListItems.forEach((row, rowIndex) => {
            try {
                let fieldType = 'Unknown';
                let fieldName = 'Unknown';
                const sourceMappings = {};
                
                // Extract field type
                const fieldTypeElement = row.querySelector('field-type .type-text');
                if (fieldTypeElement) {
                    fieldType = fieldTypeElement.textContent.trim();
                }
                
                // Extract field name
                const fieldNameElement = row.querySelector('field-name .no-wrap-ellipsis-text.no-input');
                if (fieldNameElement) {
                    fieldName = fieldNameElement.textContent.trim();
                }
                
                // DEBUG: Log what we're finding
                if (fieldName.includes('i1') || fieldName.includes('i2')) {
                    console.log(`DEBUG Row ${rowIndex + 1}: Type="${fieldType}", Name="${fieldName}"`);
                }
                
                // Extract source mappings
                const sourceFields = row.querySelectorAll('.sources-side-row');
                
                sourceFields.forEach((sourceField, sourceIndex) => {
                    try {
                        // Skip if we're processing more sources than we have data sources
                        if (sourceIndex >= dataSources.length) {
                            return;
                        }
                        
                        let mappingText = '';
                        
                        // Check for "Not mapped"
                        const notMappedElement = sourceField.querySelector('[data-key="NOT_MAPPED"]');
                        if (notMappedElement) {
                            mappingText = 'Not mapped';
                        } else {
                            // Get the actual source field mapping
                            const sourceNameSpan = sourceField.querySelector('.source-field-name span');
                            if (sourceNameSpan) {
                                const allSpans = sourceField.querySelectorAll('.source-field-name span');
                                for (let span of allSpans) {
                                    const text = span.textContent.trim();
                                    if (text && text !== 'Not mapped') {
                                        mappingText = text;
                                        break;
                                    }
                                }
                            }
                        }
                        
                        const sourceName = dataSources[sourceIndex].name;
                        sourceMappings[sourceName] = mappingText || 'Not mapped';
                        
                    } catch (error) {
                        console.warn(`Error processing source ${sourceIndex} for field ${rowIndex}:`, error);
                        const sourceName = dataSources[sourceIndex] ? dataSources[sourceIndex].name : `Source ${sourceIndex + 1}`;
                        sourceMappings[sourceName] = 'Error';
                    }
                });
                
                if (fieldType !== 'Unknown' || fieldName !== 'Unknown') {
                    processedCount++;
                    
                    const fieldData = {
                        index: processedCount,
                        fieldType: fieldType,
                        fieldName: fieldName,
                        ...sourceMappings
                    };
                    
                    fields.push(fieldData);
                    
                    if (processedCount % 10 === 0) {
                        console.log(`Processed ${processedCount} fields...`);
                    }
                }
            } catch (error) {
                console.warn(`Error processing row ${rowIndex}:`, error);
            }
        });
        
        return fields;
    }
    
    function displayAsTable(fields) {
        console.log('\n=== EXTRACTED FIELDS ===\n');
        console.table(fields);
        console.log(`\nTotal fields extracted: ${fields.length}`);
    }
    
    function convertToCSV(fields) {
        if (fields.length === 0) return '';
        
        const allKeys = new Set();
        fields.forEach(field => {
            Object.keys(field).forEach(key => allKeys.add(key));
        });
        
        const keys = Array.from(allKeys).filter(key => key !== 'index');
        const orderedHeaders = ['index', 'fieldType', 'fieldName', ...keys.filter(h => h !== 'fieldType' && h !== 'fieldName')];
        
        const headerRow = orderedHeaders.map(h => {
            if (h === 'index') return 'Index';
            if (h === 'fieldType') return 'Field Type';
            if (h === 'fieldName') return 'Field Name';
            return h;
        }).map(h => `"${h}"`).join(',');
        
        const dataRows = fields.map(field => {
            return orderedHeaders.map(key => {
                const value = field[key] || '';
                return `"${String(value).replace(/"/g, '""')}"`;
            }).join(',');
        }).join('\n');
        
        return headerRow + '\n' + dataRows;
    }
    
    function downloadCSV(csv, filename = 'qualtrics_fields.csv') {
        const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
        const link = document.createElement('a');
        const url = URL.createObjectURL(blob);
        
        link.setAttribute('href', url);
        link.setAttribute('download', filename);
        link.style.visibility = 'hidden';
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        URL.revokeObjectURL(url);
        
        console.log(`✓ Downloaded: ${filename}`);
    }
    
    function copyToClipboard(text) {
        const textarea = document.createElement('textarea');
        textarea.value = text;
        textarea.style.position = 'fixed';
        textarea.style.opacity = '0';
        document.body.appendChild(textarea);
        textarea.select();
        
        try {
            document.execCommand('copy');
            console.log('✓ CSV data copied to clipboard!');
            return true;
        } catch (err) {
            console.error('Failed to copy to clipboard:', err);
            return false;
        } finally {
            document.body.removeChild(textarea);
        }
    }
    
    console.log('Starting extraction...\n');
    const extractedFields = extractFieldData();
    
    if (extractedFields.length === 0) {
        console.error('❌ No fields found! Make sure you are on the Qualtrics Dashboard Data mapping page.');
        return;
    }
    
    displayAsTable(extractedFields);
    
    const csvData = convertToCSV(extractedFields);
    
    window.qualtricsFieldData = extractedFields;
    window.qualtricsFieldCSV = csvData;
    
    window.downloadQualtricsCSV = function(filename) {
        downloadCSV(csvData, filename || 'qualtrics_fields.csv');
    };
    
    window.copyQualtricsCSV = function() {
        return copyToClipboard(csvData);
    };
    
    window.getQualtricsJSON = function() {
        return JSON.stringify(extractedFields, null, 2);
    };
    
    window.downloadQualtricsJSON = function(filename) {
        const json = JSON.stringify(extractedFields, null, 2);
        const blob = new Blob([json], { type: 'application/json' });
        const link = document.createElement('a');
        const url = URL.createObjectURL(blob);
        
        link.setAttribute('href', url);
        link.setAttribute('download', filename || 'qualtrics_fields.json');
        link.style.visibility = 'hidden';
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        URL.revokeObjectURL(url);
        
        console.log(`✓ Downloaded: ${filename || 'qualtrics_fields.json'}`);
    };
    
    console.log('\n=== ACTIONS AVAILABLE ===');
    console.log('1. Download CSV:  downloadQualtricsCSV()');
    console.log('2. Download JSON: downloadQualtricsJSON()');
    console.log('3. Copy CSV:      copyQualtricsCSV()');
    console.log('4. View data:     qualtricsFieldData');
    console.log('5. View CSV:      qualtricsFieldCSV');
    console.log('6. View JSON:     getQualtricsJSON()');
    
    console.log('\n✓ Extraction complete! Use the commands above to export the data.');
    
})();

Paste the script into the console and press Enter

4

View the Results

The script will display a table showing all extracted fields in the console.

You should see a message like: "✓ Extraction complete! Total fields extracted: 22"
5

Export Your Data

Use any of these commands in the console to export:

downloadQualtricsCSV()   // Download as CSV file
downloadQualtricsJSON()  // Download as JSON file
copyQualtricsCSV()     // Copy to clipboard
Pro Tip: The CSV file can be opened directly in Excel, Google Sheets, or any spreadsheet application!

Understanding Your Output

What Gets Extracted

The extraction captures complete information about your Dashboard Data configuration:

Field Type Field Name Source 1 Name Source 2 Name
Date Survey Metadata - Start Date Survey Metadata - Start Date Survey Metadata - Start Date
Number Set Q1 - How likely are you to recommend... Q1 - How likely are you to recommend... Not mapped
Open Text Q2 - why did you give this score? Q2 - why did you give this score? Not mapped
Number Set Embedded Data - NPS NPS Not mapped

Field Types You'll See

Source Mappings

For each data source in your dashboard, you'll see:

Comparing Across Environments (Dev, Test, and Prod)

One of the most powerful use cases for your extracted CSV is comparing Dashboard Data field mapping configurations across Qualtrics environments. Configuration drift between Dev, Test, and Prod is one of the most common causes of dashboard data issues that are difficult to trace.

1

Extract from Development Environment

Run the script in your Dev environment and download the CSV. Save it as dashboard_field_mappings_DEV.csv.

2

Extract from Test Environment

Repeat the process in Test and save as dashboard_field_mappings_TEST.csv.

3

Extract from Production Environment

Extract from Prod and save as dashboard_field_mappings_PROD.csv.

4

Compare with Pirai AI CSV Comparator

Upload two CSV files to the Pirai AI CSV Comparator to instantly identify mismatches. The tool shows differences row by row so you can spot missing fields, field type changes, unmapped sources, and naming discrepancies without needing Excel or any external service. Your data stays in the browser.

Common configuration drift patterns

  • Missing fields : a field mapped in Dev but absent in Prod
  • Field type mismatches : Date in Dev, Text Set in Prod for the same field
  • Unmapped sources : a data source mapped in one environment but showing "Not mapped" in another
  • Field name discrepancies : naming differences between environments causing broken dashboard widgets
  • Index order differences : fields in a different sequence, which can affect dashboard display logic

Troubleshooting

Problem: "No fields found" message

  • Make sure you're on the Dashboard Data page with the field grid visible
  • Try scrolling down to load all fields before running the script
  • Refresh the page and try again

Problem: Download button doesn't work

  • Use copyQualtricsCSV() to copy to clipboard instead
  • Paste into Excel, Google Sheets, or a text editor
  • Check if your browser is blocking downloads

Problem: Script doesn't run or shows errors

  • Make sure you copied the entire script
  • Clear the console and try again
  • Refresh the Qualtrics page and run the script again

Advanced Usage

Filtering Specific Sources

After running the extraction, you can filter the data in the console:

// Get only fields mapped to a specific source
qualtricsFieldData.filter(f => f['Source Name'] !== 'Not mapped')

Custom Export Filename

downloadQualtricsCSV('my_dashboard_fields.csv')
downloadQualtricsJSON('my_dashboard_fields.json')

Use Cases

Documentation

Create comprehensive documentation of your dashboard configuration for:

Migration Planning

Plan data source migrations by:

Analysis & Optimization

Backup & Recovery

Need Help with Qualtrics Survey Conversion?

While this tool extracts dashboard mappings, if you need to convert surveys between formats, check out Pirai AI's survey automation platform. We help researchers convert Word, PDF, and Excel questionnaires into Qualtrics and 19+ other platforms in minutes.