WordPress Security

WordPress Security for Business Directory Websites

Directory websites allow user submissions which creates security risks. Learn how to protect your directory from spam, fake listings, and malicious content.

S
Sarah Chen
8 min read
1,139 views
Security guide for WordPress business directory sites

Business directories and listing websites face unique security challenges because they accept user-submitted content. This opens the door to spam, malicious content, and abuse. Proper security ensures your directory remains trustworthy and safe.

Directory Security Challenges

  • User submissions - Uncontrolled content input
  • Spam listings - Fake or promotional entries
  • Malicious content - XSS, links to malware
  • Duplicate listings - SEO manipulation
  • Payment fraud - For paid listings

Secure Listing Submissions

Input Validation and Sanitization

// Comprehensive listing validation
function validate_directory_listing($data) {
    $errors = new WP_Error();

    // Required fields
    $required = array('business_name', 'email', 'category');
    foreach ($required as $field) {
        if (empty($data[$field])) {
            $errors->add($field . '_required', ucfirst($field) . ' is required.');
        }
    }

    // Sanitize all fields
    $clean = array(
        'business_name' => sanitize_text_field($data['business_name']),
        'description' => wp_kses_post($data['description']),
        'email' => sanitize_email($data['email']),
        'phone' => preg_replace('/[^0-9+-s]/', '', $data['phone']),
        'website' => esc_url_raw($data['website']),
        'address' => sanitize_textarea_field($data['address']),
        'category' => absint($data['category'])
    );

    // Validate email format
    if (!is_email($clean['email'])) {
        $errors->add('invalid_email', 'Please provide a valid email address.');
    }

    // Validate URL if provided
    if (!empty($clean['website']) && !filter_var($clean['website'], FILTER_VALIDATE_URL)) {
        $errors->add('invalid_url', 'Please provide a valid website URL.');
    }

    // Check for spam patterns
    $spam_check = check_for_spam_content($clean);
    if ($spam_check) {
        $errors->add('spam_detected', 'Submission rejected.');
    }

    if ($errors->has_errors()) {
        return $errors;
    }

    return $clean;
}

// Check content for spam patterns
function check_for_spam_content($data) {
    $spam_patterns = array(
        '/(viagra|cialis|casino|poker|payday|loan)/i',
        '/(http[s]?://){2,}/', // Multiple URLs
        '/(.)1{10,}/', // Repeated characters
        '/[А-Яа-яЁё]/', // Cyrillic (if not expected)
    );

    $text = implode(' ', $data);

    foreach ($spam_patterns as $pattern) {
        if (preg_match($pattern, $text)) {
            return true;
        }
    }

    return false;
}

Rate Limiting Submissions

// Prevent submission abuse
function rate_limit_submissions() {
    $ip = wpfs_get_client_ip();

    // Check IP-based limit
    $ip_key = 'listing_submit_' . md5($ip);
    $ip_count = get_transient($ip_key) ?: 0;

    if ($ip_count >= 3) { // 3 submissions per hour
        return new WP_Error('rate_limited',
            'Too many submissions. Please try again later.');
    }

    set_transient($ip_key, $ip_count + 1, HOUR_IN_SECONDS);

    // Check email-based limit
    if (is_user_logged_in()) {
        $user_key = 'listing_submit_user_' . get_current_user_id();
        $user_count = get_transient($user_key) ?: 0;

        if ($user_count >= 5) { // 5 per hour for logged in users
            return new WP_Error('rate_limited',
                'Submission limit reached. Please try again later.');
        }

        set_transient($user_key, $user_count + 1, HOUR_IN_SECONDS);
    }

    return true;
}

Moderation Queue

// All submissions require approval
function submit_listing_for_review($listing_data) {
    // Create listing as pending
    $listing_id = wp_insert_post(array(
        'post_title' => $listing_data['business_name'],
        'post_content' => $listing_data['description'],
        'post_type' => 'directory_listing',
        'post_status' => 'pending' // Always pending for review
    ));

    // Store metadata
    foreach ($listing_data as $key => $value) {
        update_post_meta($listing_id, '_listing_' . $key, $value);
    }

    // Flag for spam check
    $spam_score = calculate_spam_score($listing_data);
    update_post_meta($listing_id, '_spam_score', $spam_score);

    if ($spam_score > 70) {
        update_post_meta($listing_id, '_flagged_for_spam', true);
    }

    // Notify moderators
    notify_moderators_new_listing($listing_id);

    return $listing_id;
}

// Spam score calculation
function calculate_spam_score($data) {
    $score = 0;

    // All caps title
    if ($data['business_name'] === strtoupper($data['business_name'])) {
        $score += 20;
    }

    // Excessive URLs in description
    $url_count = preg_match_all('/https?:///', $data['description']);
    $score += min($url_count * 10, 30);

    // Phone numbers in description
    if (preg_match('/d{3}[-.s]?d{3}[-.s]?d{4}/', $data['description'])) {
        $score += 10;
    }

    // Disposable email domain
    if (is_disposable_email($data['email'])) {
        $score += 40;
    }

    return $score;
}

Image Upload Security

// Secure listing image uploads
function secure_listing_image_upload($file) {
    // Allowed types
    $allowed = array('image/jpeg', 'image/png', 'image/webp');

    if (!in_array($file['type'], $allowed)) {
        $file['error'] = 'Only JPEG, PNG, and WebP images are allowed.';
        return $file;
    }

    // Max file size (2MB)
    if ($file['size'] > 2 * 1024 * 1024) {
        $file['error'] = 'Image must be smaller than 2MB.';
        return $file;
    }

    // Verify it's actually an image
    $image_info = getimagesize($file['tmp_name']);
    if ($image_info === false) {
        $file['error'] = 'Invalid image file.';
        return $file;
    }

    // Strip EXIF data for privacy
    $file = strip_exif_data($file);

    return $file;
}
add_filter('wp_handle_upload_prefilter', 'secure_listing_image_upload');

Claim/Verification System

// Business claim verification
function process_business_claim($listing_id, $claimant_data) {
    // Generate verification code
    $verification_code = wp_generate_password(20, false);

    // Store claim request
    $claim = array(
        'listing_id' => $listing_id,
        'claimant_email' => sanitize_email($claimant_data['email']),
        'claimant_name' => sanitize_text_field($claimant_data['name']),
        'verification_code' => wp_hash($verification_code),
        'status' => 'pending',
        'submitted_at' => current_time('mysql')
    );

    global $wpdb;
    $wpdb->insert($wpdb->prefix . 'listing_claims', $claim);

    // Send verification email
    wp_mail(
        $claimant_data['email'],
        'Verify Your Business Claim',
        'Your verification code: ' . $verification_code
    );

    return true;
}

Conclusion

Directory websites require robust input validation, moderation systems, and spam prevention. Always sanitize user input, require approval for submissions, and implement comprehensive spam detection.

Share:
S
Written by Sarah Chen

WP Folder Shield Team

Related Articles

SEO Spam Injection: How to Detect Hidden Links and Malicious Redirects
SEO Spam Injection: How to Detect Hidden Links and Malicious Redirects

Learn how hackers inject hidden links and malicious redirects into WordPress sites to steal your...

January 18, 2026
Understanding WordPress Malware Signatures and Detection Patterns
Understanding WordPress Malware Signatures and Detection Patterns

Learn how malware scanners detect threats using signatures and patterns. Understand the technology...

January 15, 2026
Country Blocking for WooCommerce: Protect Your Online Store
Country Blocking for WooCommerce: Protect Your Online Store

Learn how to implement country blocking for WooCommerce stores. Prevent fraud, reduce chargebacks...

January 10, 2026

Ready to Secure Your WordPress Site?

Get complete protection with WP Folder Shield.

Get Started