Hook: mam_chat_manager_get_user_avatar

Signature

apply_filters( 'mam_chat_manager_get_user_avatar', string $avatar, int $app_user_id );
Parameter Type Description
$avatar string The avatar URL the plugin already resolved. Empty string when no avatar is set.
$app_user_id int The app_user post ID (not the WordPress user ID) of the participant.

Returns: string — the final avatar URL. You must return it. Returning '' causes the mobile client to fall back to the initials avatar (colored per Recipe: Style chat bubbles and behavior).


Purpose

Replaces or augments the way mam-chat-manager resolves a chat participant’s avatar URL. The default resolution reads the _user_avatar user meta on the WP user behind the app_user. If the meta value is numeric, it’s treated as an attachment ID and resolved through wp_get_attachment_image_src() at full size; otherwise it’s used as a direct URL.

Subscribe to override based on context — vendor logo, Gravatar, role-specific avatar, marketplace-style anonymous icon, or the bundled placeholder for users who haven’t uploaded one.


When it runs

Inside mam_chat_manager_endpoints::get_user_avatar() (includes/mam_chat_manager_end_points.php:1240):

$avatar = apply_filters( 'mam_chat_manager_get_user_avatar', $avatar, $app_user_id );
return $avatar ?: '';

get_user_avatar() is called on every API response that includes participant info: thread list responses, individual thread responses, and through Hook: mam_add_chat_to_detail on detail-screen responses.

Unlike get_display_name(), the avatar resolver does not cache its result within the request. Each call re-runs your filter.


Example: vendor logo for sellers, Gravatar for everyone else

add_filter( 'mam_chat_manager_get_user_avatar', 'my_app_vendor_or_gravatar', 10, 2 );

function my_app_vendor_or_gravatar( $avatar, $app_user_id ) {
    $wp_user_id = (int) get_post_meta( $app_user_id, 'user_id', true );
    if ( ! $wp_user_id ) {
        return $avatar;
    }

    // 1) Vendor business logo, if present.
    $logo_id = (int) get_user_meta( $wp_user_id, 'vendor_logo_attachment_id', true );
    if ( $logo_id ) {
        $src = wp_get_attachment_image_src( $logo_id, 'full' );
        if ( ! empty( $src[0] ) ) {
            return $src[0];
        }
    }

    // 2) Existing _user_avatar value (the upstream resolution).
    if ( ! empty( $avatar ) ) {
        return $avatar;
    }

    // 3) Gravatar fallback.
    $user = get_userdata( $wp_user_id );
    if ( $user && $user->user_email ) {
        return 'https://secure.gravatar.com/avatar/' . md5( strtolower( trim( $user->user_email ) ) ) . '?s=256&d=mp';
    }

    return $avatar;
}

Example: anonymized avatars in a marketplace

add_filter( 'mam_chat_manager_get_user_avatar', 'my_app_anonymize_avatar', 10, 2 );

function my_app_anonymize_avatar( $avatar, $app_user_id ) {
    if ( has_sent_message( $app_user_id ) ) {
        return $avatar;
    }
    return ''; // Render the initials avatar until the user actively reaches out.
}

Pair with Hook: mam_chat_set_chat_user_name to anonymize both the name and the avatar consistently.


Example: per-admin avatar in support chat

add_filter( 'mam_chat_manager_get_user_avatar', 'my_app_admin_avatar_passthrough', 10, 2 );

function my_app_admin_avatar_passthrough( $avatar, $app_user_id ) {
    $wp_user_id = (int) get_post_meta( $app_user_id, 'user_id', true );
    if ( ! $wp_user_id ) {
        return $avatar;
    }

    $user = get_userdata( $wp_user_id );
    if ( ! $user || ! in_array( 'administrator', (array) $user->roles, true ) ) {
        return $avatar;
    }

    // Each admin keeps their own avatar instead of the global support-chat logo.
    return get_avatar_url( $wp_user_id, [ 'size' => 256 ] ) ?: $avatar;
}

In combination with Hook: mam_chat_set_chat_user_name‘s per-admin attribution example, this produces a support-chat thread where every reply is attributed to the specific admin who wrote it — name and avatar both.


Gotchas

  • You receive an app_user post ID, not a WP user ID. Convert with get_post_meta( $app_user_id, 'user_id', true ) before reading WP user data.
  • An empty string is a valid return value. It tells the mobile client to render the initials avatar with the configured chat_avatar_color. Returning null, false, or 0 gets coerced to '' by the wrapping ?: '' after your filter, but downstream consumers in the JSON pipeline are stricter — always return a string.
  • No per-request cache. Repeated avatar lookups within the same request will run your filter every time. Heavy callbacks (a database query per call, an external HTTP request) can show up in the thread-list response time. Cache inside your callback if needed.
  • Attachment IDs are not auto-resolved after the filter. The plugin resolves attachment IDs before running the filter — if your callback returns a numeric attachment ID, it is sent to the mobile client as-is and will not render. Resolve to a URL inside your callback.
  • Mobile clients expect HTTPS. Returning an http:// URL works on most platforms but app-store reviews flag it. Prefer HTTPS sources or proxy through your own CDN.

Verification

This article was last verified against:

  • Plugin: mam-chat-manager v2.0.0
  • Source: includes/mam_chat_manager_end_points.php (get_user_avatar())

Re-verify whenever the _user_avatar resolution path changes, attachment-ID handling moves, the filter signature gains additional arguments, or the post-filter ?: '' coercion is removed.


  • Plugin: mam-chat-manager
  • Recipe: Style chat bubbles and behavior — the initials-avatar fallback color is configured here
  • Recipe: Configure the admin support chat — sets the global support-chat avatar; this filter overrides it per-message
  • Hook: mam_chat_set_chat_user_name — companion filter for the display name
  • Hook: mam_add_chat_to_detail — calls get_user_avatar() when assembling detail payloads

Metadata

Field Value
Article type Hook Reference
Plugin slug mam-chat-manager
Applies to plugin version 2.0.0+
Category Extending MAM Suite
Hook type filter
Audience PHP developer
Last verified 2026-05-01
Contents

    Need Support?

    Can’t find the answer you’re looking for? Don’t worry we’re here to help!