Imagine your customers sharing photos of themselves using your product directly within the review section, or blog readers sharing relevant images alongside their comments. This isn’t just possible; it’s a powerful way to build community and provide social proof.
While many plugins offer this functionality, adding it directly with custom code gives you more control, potentially better performance, and avoids the overhead of a full plugin.

In this post, I’ll guide you through adding image upload capability to your standard WordPress comments and WooCommerce product reviews using custom code snippets.

Why Image Uploads in Comments Matter

Visual content has a unique power to engage users. By allowing visitors to upload images in comments or product reviews, you can:

  • Boost interaction : Users are more likely to leave detailed feedback with visuals.
  • Build trust : Authentic photos from real customers enhance credibility.
  • Improve product insights : For WooCommerce stores, image-based reviews help showcase product quality or issues.

While plugins can achieve this, custom code offers lightweight, secure, and tailored solutions. Let’s dive in!

Important Notes Before You Start

⚠️ Always Use a Child Theme : Never edit your parent theme’s functions.php directly—updates will erase your changes.
💾 Back Up Your Site : Code errors can break your site; use a backup plugin like UpdraftPlus.
🛠 Basic Coding Knowledge : Familiarize yourself with FTP, file editors, and PHP syntax.

Add Image Uploads to WordPress Comments Without Plugins

This is the complete code for the free version functionality. You will add this to your child theme’s functions.php file.
Simply paste the code between the existing <?php and ?> or at the very end if the ?> is omitted, which is common practice.

You must create a child theme before making any changes to functions.php file. Otherwise, the applied changes will be lost after each update.
Create child theme in WordPress step by step [without plugin]

As an alternative method, you can use the Code Snippets plugin to insert your codes into WordPress.

Show code
/**
 * Plugin Name: Comment Image Upload
 * Plugin URI: https://redpishi.com/wordpress-tutorials/comment-image-upload/
 * Description: Allows users to upload images with their comments
 * Author: WPCookie
 */

// Exit if accessed directly
if (!defined('ABSPATH')) {
    exit;
}

class Comment_Image_Upload {

    public function __construct() {
        // Add the upload field to comment form
        add_filter('comment_form_field_comment', array($this, 'add_image_upload_field'), 10, 2);

        // Handle the image upload
        add_action('comment_post', array($this, 'save_comment_image'), 10, 1);

        // Display the image with the comment
        add_filter('comment_text', array($this, 'display_comment_image'), 10, 2);

        // Modify HTML form to allow file uploads
        add_filter('comment_form_defaults', array($this, 'modify_comment_form'));

        // Add admin column for image
        add_filter('manage_edit-comments_columns', array($this, 'add_comment_image_column'));
        add_action('manage_comments_custom_column', array($this, 'comment_image_column_content'), 10, 2);

        // Enqueue required styles
        add_action('wp_enqueue_scripts', array($this, 'enqueue_styles'));

		add_action('delete_comment', array($this, 'delete_comment_image'), 10, 1);
    }

    /**
     * Add the image upload field to comment form
     */
    public function add_image_upload_field($comment_field, $args = array()) {
    $image_field = '<p class="comment-form-image">';
    $image_field .= '<label for="comment-image">' . __('Upload Image (JPG, PNG, GIF)', 'comment-image-upload') . '</label><br />';
    $image_field .= '<input type="file" id="comment-image" name="comment-image" accept="image/jpeg,image/png,image/gif" />';
    $image_field .= '</p>';

    return $comment_field . $image_field;
}

    /**
     * Modify comment form to accept file uploads
     */
   public function modify_comment_form($defaults) {

    $defaults['enctype'] = 'multipart/form-data';
    return $defaults;
}

    /**
     * Save uploaded image as comment meta
     */
    public function save_comment_image($comment_id) {

		// Basic validation
		if (!$comment_id || !isset($_FILES['comment-image'])) {
			return;
		}

		// Check if file was actually uploaded
		if (empty($_FILES['comment-image']['name']) || $_FILES['comment-image']['error'] !== UPLOAD_ERR_OK) {
			return;
		}
        // Verify file is an image
        $file_info = wp_check_filetype($_FILES['comment-image']['name']);
        $allowed_types = array('jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif');

        if (!in_array($file_info['type'], $allowed_types)) {
            return;
        }

        // WordPress upload handling
        require_once(ABSPATH . 'wp-admin/includes/file.php');
        require_once(ABSPATH . 'wp-admin/includes/image.php');
        require_once(ABSPATH . 'wp-admin/includes/media.php');

        // Upload the file and get the attachment ID
        $attachment_id = media_handle_upload('comment-image', 0);

        if (is_wp_error($attachment_id)) {
            return;
        }

        // Set attachment to pending if comment moderation is enabled
        $comment_approved = get_comment($comment_id)->comment_approved;
        wp_update_post(array(
            'ID' => $attachment_id,
            'post_status' => ($comment_approved === '1') ? 'inherit' : 'pending'
        ));

        // Link attachment to comment
        update_comment_meta($comment_id, 'comment_image_id', $attachment_id);

        // Update attachment post parent to the comment's post ID
        $comment = get_comment($comment_id);
        wp_update_post(array(
            'ID' => $attachment_id,
            'post_parent' => $comment->comment_post_ID
        ));
    }

    /**
     * Display image with the comment
     */
    public function display_comment_image($comment_text, $comment = null) {
    // Safely get the comment object
    if (is_null($comment)) {
        $comment = get_comment();
        if (!$comment) {
            return $comment_text; // Return original text if no comment found
        }
    }

    // Check if comment exists and has an ID
    if (!isset($comment->comment_ID)) {
        return $comment_text;
    }

    // Get the attachment ID
    $attachment_id = get_comment_meta($comment->comment_ID, 'comment_image_id', true);

    // If no image, return original text
    if (!$attachment_id) {
        return $comment_text;
    }

    // Only show image if comment is approved
    if ($comment->comment_approved == '1') {
    $image_html = wp_get_attachment_image($attachment_id, 'medium'); // 'medium' | 'large' | 'full'
		if ($image_html) {
        // Get the full-size image URL
        $full_image_url = wp_get_attachment_image_url($attachment_id, 'full');
		$comment_text .= '<div class="comment-image">';
        $comment_text .= '<a href="' . esc_url($full_image_url) . '" target="_blank" rel="noopener noreferrer">';
        $comment_text .= $image_html;
        $comment_text .= '</a>';
        $comment_text .= '</div>';

    }
}

    return $comment_text;
}

    /**
     * Add column to comments admin screen
     */
    public function add_comment_image_column($columns) {
        $columns['comment_image'] = __('Image', 'comment-image-upload');
        return $columns;
    }

    /**
     * Display thumbnail in admin column
     */
    public function comment_image_column_content($column, $comment_id) {
        if ($column !== 'comment_image') {
            return;
        }

        $attachment_id = get_comment_meta($comment_id, 'comment_image_id', true);

        if ($attachment_id) {
            echo wp_get_attachment_image($attachment_id, array(50, 50));
        }
    }

    /**
     * Add styles for the comment image
     */
    public function enqueue_styles() {
        if (is_singular() && comments_open()) {
            wp_add_inline_style('comment-reply', '
                .comment-form-image {
                    margin-bottom: 15px;
                }
                .comment-image-wrapper {
                    margin-top: 15px;
                    max-width: 100%;
                }
                .comment-image-wrapper img {
                    max-width: 100%;
                    height: auto;
                    border-radius: 4px;
                }
            ');
        }
    }

    /**
     * Handle comment approval - approve the attached image too
     */
    public function approve_comment_image($new_status, $old_status, $comment) {
        if ($new_status !== $old_status && $new_status === 'approved') {
            $attachment_id = get_comment_meta($comment->comment_ID, 'comment_image_id', true);

            if ($attachment_id) {
                wp_update_post(array(
                    'ID' => $attachment_id,
                    'post_status' => 'inherit'
                ));
            }
        }
    }

	/**
	 * Delete associated image when comment is deleted
	 */
	public function delete_comment_image($comment_id) {
		$attachment_id = get_comment_meta($comment_id, 'comment_image_id', true);

		if ($attachment_id) {
			// Force delete the image (skip trash)
			wp_delete_attachment($attachment_id, true);

			// Optional: Delete the comment meta as well
			delete_comment_meta($comment_id, 'comment_image_id');
		}
	}

}

// Initialize the plugin
$comment_image_upload = new Comment_Image_Upload();

// Hook for comment approval
add_action('transition_comment_status', array($comment_image_upload, 'approve_comment_image'), 10, 3);




add_action('wp_footer', function() {
    if (is_singular() && comments_open()) {
        ?>
        <script>
            (function() {
                var forms = document.getElementsByTagName('form');
                for (var i = 0; i < forms.length; i++) {
                    if (forms[i].action && forms[i].action.indexOf('wp-comments-post.php') > -1) {
                        forms[i].enctype = 'multipart/form-data';
                        console.log('Enabled file upload for comment form');
                    }
                }
            })();
        </script>
        <?php
    }
});

Key Features

  • Single image upload per comment
  • Admin approval through standard comment moderation
  • Automatic image deletion when a comment is deleted
  • Images open in a new tab when clicked
  • Basic security validation for file types and size

How It Looks in Admin and Frontend

On the frontend:

  • Comment form includes an “Upload an image” field
  • Approved comments display the uploaded image below the text
  • Images are responsive and fit within the comment container
  • Clicking an image opens it in a new tab for full-size viewing

In the admin area:

  • Comment moderation includes the attached image
  • Admin can approve comments as usual with attached images visible

Enable Multiple Image Uploads in WordPress Comments with Lightbox

For those looking for more advanced functionality, the this version offers a richer experience for both commenters and administrators.
Implementing the Plus version follows a similar process to the Standard version: access your child theme’s functions.php, paste the premium code, save, and upload.

Show Code (The Plus Version for WPCookie Members)

This code is for WPCookie PLUS+ members only.

Join WPCookie PLUS+
Already a member? Log in here

Enhanced Features of the Plus Version:

  • Multiple Image Uploads: Allows users to upload up to a specified number of images (e.g., 5) per comment.
  • Lightbox Display: Images on the frontend open in a modern lightbox gallery overlay when clicked, keeping visitors on your page.

Standard vs. Plus Feature Comparison

FeatureStandard VersionPlus Version (WPCookie)
Max Images per Comment1Up to 5
Image Display (Click)Opens in New TabLightbox Gallery
Multiple ImagesNot SupportedYes, with Navigation
Is this method secure?

Yes, the implementation includes file type validation, size limits, and proper file handling. However, you should always keep your WordPress core, themes, and plugins updated for maximum security Voxfor.

Will this work with any theme?

Yes, this implementation should work with most WordPress themes. However, some themes might need minor CSS adjustments to match your design.

What happens to uploaded images when a comment is deleted?

With the code provided, images are automatically deleted from the server when the associated comment is deleted.

Final Thoughts

By following this guide, you’ll not only add a valuable feature to your WordPress or WooCommerce site but also do so in a way that’s optimized for performance and user engagement. If you encounter any issues, remember to revert to your backup and test incrementally to pinpoint errors. Happy coding!

Share this post
Maya
Maya

Hi, my name is Maya and I’m a WordPress plugin developer. I created this website to share some of the helpful codes that I’ve used in my own projects.
If you’re looking for a custom plugin for your website, you can contact me by clicking on Hire a developer in the menu. I’d love to hear from you.

Articles: 61