/

Universal Typeform Creator

Copy script

Copied

Copy script

Copied

Universal Typeform Creator

Creates customizable Typeform surveys with flexible question types, themes, and settings. Supports multiple choice, text input, email collection, rating scales, and more. Perfect for surveys, feedback forms, lead generation, and data collection with automatic verification.

Created by

andrew van beek - Keyboard Team

Requirements

typeform.com logo

Script

Copy script

Copied

Copy script

Copied

const axios = require('axios');

console.log('šŸ“‹ Universal Typeform Creator Starting...');
console.log('='.repeat(50));

// Get Typeform API token
const typeformToken = process.env.KEYBOARD_TYPEFORM;

if (!typeformToken) {
    console.log('āŒ Error: KEYBOARD_TYPEFORM token not found in environment variables');
    return;
}

// Parse template variables
const formTitle = '{{title}}';
const welcomeTitle = '{{welcomeTitle}}';
const welcomeDescription = '{{welcomeDescription}}';
const thankYouTitle = '{{thankYouTitle}}';
const thankYouDescription = '{{thankYouDescription}}';
const questions = {{questions}};
const collectEmail = {{collectEmail}};
const emailOptional = {{emailOptional}};
const enableProgressBar = {{enableProgressBar}};
const isPublic = {{isPublic}};

console.log(`šŸ“ Creating form: "${formTitle}"`);
console.log(`šŸ“Š Number of questions: ${questions.length}`);
if (collectEmail) {
    console.log(`šŸ“§ Email collection: ${emailOptional ? 'Optional' : 'Required'}`);
}

// Build the form structure
const typeformData = {
    title: formTitle,
    settings: {
        language: "en",
        progress_bar: enableProgressBar ? "proportion" : "none",
        meta: {
            allow_indexing: false
        },
        hide_navigation: false,
        is_public: isPublic,
        show_progress_bar: enableProgressBar,
        show_typeform_branding: true
    },
    welcome_screens: [
        {
            ref: "welcome_screen",
            title: welcomeTitle,
            properties: {
                show_button: true,
                button_text: "Start Survey",
                description: welcomeDescription
            }
        }
    ],
    thankyou_screens: [
        {
            ref: "thankyou_screen", 
            title: thankYouTitle,
            properties: {
                show_button: false,
                share_icons: true,
                description: thankYouDescription
            }
        }
    ],
    fields: []
};

// Process questions and add to form
questions.forEach((question, index) => {
    const fieldRef = `question_${index + 1}`;
    const field = {
        ref: fieldRef,
        type: question.type,
        title: question.title,
        validations: {
            required: question.required || false
        }
    };

    // Add properties based on question type
    if (question.type === 'multiple_choice') {
        field.properties = {
            randomize: question.randomize || false,
            allow_multiple_selection: question.allowMultiple || false,
            allow_other_choice: question.allowOther || false,
            choices: (question.choices || []).map(choice => ({
                label: typeof choice === 'string' ? choice : choice.label
            }))
        };
    } else if (question.type === 'opinion_scale') {
        field.properties = {
            start_at_one: question.startAtOne || true,
            steps: question.steps || 10,
            labels: question.labels || {}
        };
    } else if (question.type === 'rating') {
        field.properties = {
            steps: question.steps || 5,
            shape: question.shape || "star"
        };
    } else if (question.type === 'long_text' || question.type === 'short_text') {
        field.properties = {
            description: question.description || ""
        };
    } else if (question.type === 'yes_no') {
        field.properties = {};
    }

    typeformData.fields.push(field);
});

// Add email collection if requested
if (collectEmail) {
    typeformData.fields.push({
        ref: "email_collection",
        type: "email", 
        title: "What's your email address?",
        properties: {
            description: emailOptional ? "Optional - we'll only use this to follow up if needed" : "We'll only use this to follow up if needed"
        },
        validations: {
            required: !emailOptional
        }
    });
}

async function createTypeform() {
    try {
        console.log('šŸš€ Creating Typeform via API...');
        
        const response = await axios.post('https://api.typeform.com/forms', typeformData, {
            headers: {
                'Authorization': `Bearer ${typeformToken}`,
                'Content-Type': 'application/json'
            }
        });

        if (response.data && response.data.id) {
            const formId = response.data.id;
            const formUrl = `https://form.typeform.com/to/${formId}`;
            
            console.log('āœ… Typeform created successfully!');
            console.log('šŸ“‹ Form Details:');
            console.log(`   Title: ${formTitle}`);
            console.log(`   Form ID: ${formId}`);
            console.log(`   Public URL: ${formUrl}`);
            console.log(`   Admin URL: https://admin.typeform.com/form/${formId}`);
            console.log(`   Total Questions: ${typeformData.fields.length}`);
            
            // Verification
            console.log('\\nšŸ” Verifying form creation...');
            try {
                const verifyResponse = await axios.get(`https://api.typeform.com/forms/${formId}`, {
                    headers: {
                        'Authorization': `Bearer ${typeformToken}`
                    }
                });
                
                console.log('āœ… VERIFICATION: Form successfully created and accessible');
                console.log(`   Form Status: ${verifyResponse.data.settings.is_public ? 'Public' : 'Private'}`);
                console.log(`   Created: ${verifyResponse.data.created_at}`);
                console.log(`   Questions: ${verifyResponse.data.fields.length}`);
                
                // Show question breakdown
                console.log('\\nšŸ“Š Question Types:');
                const questionTypes = {};
                verifyResponse.data.fields.forEach(field => {
                    questionTypes[field.type] = (questionTypes[field.type] || 0) + 1;
                });
                Object.entries(questionTypes).forEach(([type, count]) => {
                    console.log(`   ${type}: ${count}`);
                });
                
            } catch (verifyError) {
                console.log('āš ļø Form created but verification failed:', verifyError.response?.status || verifyError.message);
            }
            
            console.log('\\nšŸŽ‰ SUCCESS! Your Typeform is ready!');
            console.log(`šŸ”— Share this URL: ${formUrl}`);
            
            return {
                success: true,
                formId: formId,
                formUrl: formUrl,
                adminUrl: `https://admin.typeform.com/form/${formId}`,
                title: formTitle,
                questionCount: typeformData.fields.length
            };
            
        } else {
            console.log('āš ļø Unexpected response format:', response.data);
            return { success: false, error: 'Unexpected response format' };
        }
        
    } catch (error) {
        console.log('āŒ Error creating Typeform:');
        if (error.response) {
            console.log('Status:', error.response.status);
            console.log('Error details:', JSON.stringify(error.response.data, null, 2));
            
            if (error.response.status === 401) {
                console.log('šŸ’” Authentication issue - check your KEYBOARD_TYPEFORM token');
            } else if (error.response.status === 403) {
                console.log('šŸ’” Permission issue - ensure your token has form creation permissions');
            } else if (error.response.status === 429) {
                console.log('šŸ’” Rate limit exceeded - wait a bit before trying again');
            }
        } else {
            console.log('Network or other error:', error.message);
        }
        return { success: false, error: error.message };
    }
}

// Execute the function
createTypeform();