I am developing a WordPress theme and using the following php code and JavaScript code, I replaced the Gravatar link with a button to upload profile image using Wordpress media library, the media library window opens successfully and I select the image but the problem is that the image is not saved or changed in the top admin bar or in The front end, and it does not appear on the profile page after i click update profile, so how do i do it?

I hope I can find help and solution here

php code in functions.php

// Enqueue scripts
function enqueue_custom_scripts()
  $screen = get_current_screen();

  // Check if it's the profile.php page
  if ($screen->id === 'profile') {
    // Enqueue jQuery

    // Enqueue the WordPress media library

    // Enqueue custom script
    wp_enqueue_script('custom-profile-script', ZED_ESTATE_THEME_SCRIPTS . '/custom-profile-script.js', array('jquery'), wp_rand(), true);

    // Localize script with nonce
    wp_localize_script('custom-profile-script', 'custom_profile_script_vars', array(
      'nonce' => wp_create_nonce('custom_profile_script_nonce'),
      'ajaxurl' => admin_url('admin-ajax.php'),
add_action('admin_enqueue_scripts', 'enqueue_custom_scripts');

// Save user profile picture
function save_user_profile_picture()
  // Verify the nonce
  if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'custom_profile_script_nonce')) {
    wp_send_json_error('Invalid nonce');

  // Get the image URL from the AJAX request
  $image_url = isset($_POST['image_url']) ? esc_url_raw($_POST['image_url']) : '';

  // Update the user's meta data with the new image URL
  if (!empty($image_url)) {
    update_user_meta(get_current_user_id(), 'profile_picture', $image_url);
    wp_send_json_success('Image saved successfully!');
  } else {
    wp_send_json_error('Image URL is empty');
add_action('wp_ajax_save_user_profile_picture', 'save_user_profile_picture');

Javascript code in separate file

jQuery(document).ready(function ($) {
  // Function to replace Gravatar link with a button
  function replaceGravatarLink() {
    // Replace the Gravatar link with a button
    $('.user-profile-picture td').html('<input type="button" id="upload-profile-picture" class="button" value="Upload from Media Library">');

    // Add a click event to the button
    $('#upload-profile-picture').on('click', function () {
      // Open the media library frame
      var mediaLibraryFrame = wp.media({
        title: 'Upload Profile Picture',
        button: { text: 'Select' },
        multiple: false

      // When an image is selected from the media library
      mediaLibraryFrame.on('select', function () {
        var attachment = mediaLibraryFrame.state().get('selection').first().toJSON();
        // Save the selected image URL to the user profile

      // Open the media library

  // Function to save the selected image URL to the user profile
  function saveUserProfilePicture(imageUrl) {
    var data = {
      action: 'save_user_profile_picture',
      nonce: custom_profile_script_vars.nonce,
      image_url: imageUrl

    // Make an AJAX request to save the image URL
    $.post(custom_profile_script_vars.ajaxurl, data, function (response) {
      if (response.success) {
        // Optionally, you can update the UI to show the new image
        console.log('Image saved successfully!');
      } else {
        console.error('Failed to save image.');

  // Check if the Gravatar link is present
  var gravatarLink = $('.user-profile-picture .description a[href="https://en.gravatar.com/"]');
  if (gravatarLink.length) {
    // Remove the Gravatar link

    // Replace it with the button

// ============================================================
jQuery(document).ready(function ($) {
  $('#upload-profile-picture').on('click', function (e) {

    // If the media frame already exists, reopen it.
    if (file_frame) {

    // Create a new media frame
    var file_frame = wp.media({
      title: 'Select or Upload a Profile Picture',
      button: {
        text: 'Use this picture'
      multiple: false  // Set to true to allow multiple files to be selected

    // When an image is selected in the media frame...
    file_frame.on('select', function () {
      // Get media attachment details from the frame state
      var attachment = file_frame.state().get('selection').first().toJSON();

      // Send the attachment URL to our custom input field.

    // Finally, open the modal on click
  • note that you should be saving the images ID, not its URL, as that makes it very difficult to figure out who the user is based on the attachment and it makes it very very hard to render the avatar correctly with srcset and sizes and for plugins to filter it as you then need to reverse engineer the ID from the URL. Other than that your code looks like it will save an image to a user meta, but there's nothing to filter the avatar functions to replace the gravatar URL with your own. Also is there a reason you used the old legacy admin ajax API instead of a modern REST API endpoint?
    – Tom J Nowell
    Nov 16, 2023 at 13:11
  • @tom-j-nowell , I'll be honest with you, I got some of these codes from GPT because I'm still a bit of a beginner, so I want to modify the code to implement the functionality I want. Nov 16, 2023 at 13:38


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.