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)
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
Feature | Standard Version | Plus Version (WPCookie) |
---|---|---|
Max Images per Comment | 1 | Up to 5 |
Image Display (Click) | Opens in New Tab | Lightbox Gallery |
Multiple Images | Not Supported | Yes, with Navigation |
FAQs About Implementation
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!