Signature
do_action( 'mam_chat_add_to_chat_thread', array $args );
| Parameter | Type | Description |
|---|---|---|
$args |
array | Message-and-thread bundle. See the table below. |
$args keys:
| Key | Type | Required | Description |
|---|---|---|---|
message |
string | yes | The message body. Trimmed; empty messages are silently dropped. |
conversation_id |
string | one of conversation_id / participant set |
The opaque mam: token for the thread. Preferred when known. |
post_id |
int | with participant set | Context post ID. Used to build the token if conversation_id is absent. |
user_ids |
int[] | with participant set | WP user IDs of explicit individual participants. |
group_ids |
int[] | with participant set | mam-chat-group post IDs. |
sender_id |
int | optional | WP user ID of the message sender. Defaults to mam_user_id() (the current MAM session). |
Returns: nothing — this is an action, not a filter. The handler returns an internal status array, but action subscribers cannot read the return value.
Purpose
mam_chat_add_to_chat_thread lets server-side code post a chat message on a user’s behalf. Common use cases:
- Posting an automated welcome message into a thread the user just opened
- Forwarding an external event (a quote acceptance, a status change, an order update) into a thread as a system message attributed to a real user
- Bulk-seeding messages from a migration script
The action does the same work as the user-facing mam_chat_send_message API endpoint: it resolves the thread (creating it if needed), inserts a mam-chat-message CPT, marks the message as already read for the sender, and dispatches push notifications to every other participant via mam_notification_send_message.
When it runs
Whenever any code calls do_action( 'mam_chat_add_to_chat_thread', $args ). The plugin registers mam_chat_manager_endpoints::add_to_chat_thread() at default priority (10).
Inside the handler:
- The
messageis trimmed; empty messages returnfalseimmediately and no message is posted. - If
conversation_idis provided, it is used directly. Otherwise the handler builds a token frompost_id+user_ids+group_ids(after converting WP user IDs to app_user IDs). - The thread is resolved with
create=true— if no thread matches the token, a newmam-chat-threadCPT is inserted, itsmam_thread_keyis populated, and the participant index is built. - The
sender_idis resolved (falling back tomam_user_id()), converted to its app_user ID. If no sender can be resolved, the call returnsfalse. - A
mam-chat-messageCPT is inserted as a child of the thread, withpost_author= sender app_user ID andpost_contentsanitized viasanitize_text_field(). - The thread’s
mam_thread_last_read_{sender}pointer is advanced to the new message ID — so the sender does not see the message they just posted as unread. - A canonical
conversation_idis rebuilt from the persisted thread metadata, and a push payload is assembled for every participant except the sender. Ifmam_notification_send_messagehas at least one subscriber, the push is dispatched.
Example: post a welcome message into a fresh thread
do_action(
'mam_chat_add_to_chat_thread',
[
'message' => 'Welcome to Acme Marketplace! Tap a listing to start a conversation with the seller.',
'post_id' => 0,
'user_ids' => [ $welcome_bot_wp_user_id, $new_user_wp_user_id ],
'group_ids' => [],
'sender_id' => $welcome_bot_wp_user_id,
]
);
If a thread between the welcome-bot user and the new user does not yet exist, this call creates one, posts the message, and pushes a notification to the new user.
Example: post a system update into an existing listing thread
$conversation_id = apply_filters(
'mam_get_thread_id_for_conversation',
0,
[ $buyer_app_user_id ],
[ $listing_staff_group_id ],
$listing_post_id,
false
);
do_action(
'mam_chat_add_to_chat_thread',
[
'conversation_id' => $conversation_id,
'message' => 'Your inquiry has been routed to our weekend team.',
'sender_id' => $listing_owner_wp_user_id,
]
);
When the conversation_id is known up-front, pass it directly — the handler skips the participant-set resolution path entirely.
Example: forward an order-status webhook
add_action( 'my_app_order_status_changed', function ( $order_id, $new_status ) {
$order = wc_get_order( $order_id );
$vendor_id = (int) get_post_field( 'post_author', $order->get_items()[0]->get_product_id() );
$customer_id = $order->get_customer_id();
do_action(
'mam_chat_add_to_chat_thread',
[
'message' => sprintf( 'Order #%d is now %s.', $order_id, $new_status ),
'post_id' => $order_id,
'user_ids' => [ $vendor_id, $customer_id ],
'sender_id' => $vendor_id,
]
);
}, 10, 2 );
Gotchas
- Empty messages are silently dropped. An
''or whitespace-only message logs nothing; the action returns without error. If you’re debugging a missing system message, check that the message body actually has content aftertrim(). - The sender must be a real MAM user.
sender_idis converted to an app_user post ID. If the WP user has no corresponding app_user CPT, the call drops without sending. The simplest workaround is to seed a dedicated “system” WP user and ensure it has a matching app_user record. - Push notifications go through
mam_notification_send_message. If no subscriber is attached to that action (e.g. on a development site without push wired up), no push is dispatched but the message is still inserted. The mobile client will see the new message on the next refresh; the user just won’t get a banner. - The sender’s read pointer advances automatically. The plugin marks the new message as read for the sender so the sender does not see their own outbound message as unread. Recipients’ unread counts update on their next phone-data request.
conversation_idis rebuilt before push dispatch. The token sent in the push payload is recomputed from the persistedmam_thread_usersandmam_thread_groupsof the thread, not from whatever you passed in$args. This is intentional — it keeps the mobile client’s cachedconversation_idin sync if the thread participants have drifted.- Always pass at least one of
conversation_idor a participant set. Passing only amessageproduces a thread keyedmam:eyJ2IjoyLCJwb3N0X2lkIjowLCJ1c2VycyI6W10sImdyb3VwcyI6W119— the empty-payload bucket. Multiple unrelated callers will all post into the same orphan thread.
Verification
This article was last verified against:
- Plugin:
mam-chat-managerv2.0.0 - Source:
includes/mam_chat_manager_end_points.php(add_to_chat_thread())
Re-verify whenever the $args key set changes, the participant-set token build path is moved, the push-payload shape changes, or the sanitization on post_content (sanitize_text_field()) is replaced.
Related articles
- Plugin: mam-chat-manager
- Hook: mam_add_chat_to_detail — resolve the
conversation_idyou’ll pass back into this action - Hook: mam_chat_set_chat_user_name — control the name shown on the new message
- Hook: mam_chat_manager_get_user_avatar — control the avatar shown on the new message
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 | action |
| Audience | PHP developer |
| Last verified | 2026-05-01 |
