A customer asks you to delete everything you hold on them. You open Tools, Erase Personal Data, send the request, and the finished report says your support chat plugin removed zero items, even though it has stored every conversation since activation. That gap usually gets closed by someone grepping the database by hand.
Chat transcripts are different from ordinary user meta because they are the raw material for emotion recognition in conversation: labeling each utterance with an emotion based on what came before it and on who is speaking. A post on Towards Data Science by Biju Puthan Veetil looks back at a 2024 thesis model, EmoNet, and what he would rebuild now that the field runs on LLMs. The architecture changed completely. The data requirement underneath it did not.
What emotion recognition in conversation collects
EmoNet’s main idea was a global speaker identity. Earlier systems scoped speaker IDs to one dialogue, so the same person became a stranger in every new conversation. The thesis gave every speaker a dataset-wide ID and a GRU that compressed their last N utterances into a single vector. Two years on, the top systems do the same thing in text: BiosERC injects LLM-written speaker biographies and LaERC-S tunes on speaker characteristics, which lands close to feeding persona history into fine-tuning.
The ablation table is the honest part of the post. Global speaker identity alone dropped weighted F1 from 37.85 to 29.43, and only the behaviour module that consumed the history earned it back, ending at 39.18 on EmoryNLP, 1.81 over the baseline.
a feature isn’t valuable in isolation; it’s valuable in combination with the machinery that consumes it
The part the papers skip
Every one of those systems assumes you can keep per-person history for as long as it helps. On a WordPress site that history lives in user meta or a custom table, and the privacy tools ignore both until you say so. The eraser loop iterates callbacks registered on wp_privacy_personal_data_erasers, and the key for every callback is the person’s email address, because guests chat too. Register nothing and the report stays at zero while the data sits there.
<?php
add_filter( 'wp_privacy_personal_data_erasers', 'bbioon_register_chat_eraser' );
function bbioon_register_chat_eraser( $erasers ) {
$erasers['bbioon-chat'] = array(
'eraser_friendly_name' => __( 'Support chat profile', 'bbioon' ),
'callback' => 'bbioon_erase_chat_profile',
);
return $erasers;
}
function bbioon_erase_chat_profile( $email, $page = 1 ) {
$user = get_user_by( 'email', $email );
if ( $page > 1 || ! $user ) {
return array(
'items_removed' => false,
'items_retained' => false,
'messages' => array(),
'done' => true,
);
}
$removed = 0;
foreach ( get_user_meta( $user->ID ) as $key => $rows ) {
if ( str_starts_with( $key, 'bbioon_erc_' ) ) {
delete_user_meta( $user->ID, $key );
$removed++;
}
}
return array(
'items_removed' => $removed > 0,
'items_retained' => false,
'messages' => array( sprintf( 'Removed %d profile keys.', $removed ) ),
'done' => true,
);
}
Calling get_user_meta() with only a user ID returns every meta row as an array, which is what makes that loop work, and the prefix check keeps you from deleting meta your plugin does not own. Raw transcripts in a custom table need a second eraser, using the $page parameter to delete in batches so a big account cannot time it out.
Generated profiles are a gray zone. BiosERC’s biographies are LLM-written, not copied from chats, and I’m not sure a regulator would treat them as less personal than the transcripts they summarize. Register them anyway.
Where I’d draw the line
Text-only recognition is lossy. The post’s own example is “Oh, great.”, sincere or sarcastic and identical on the page, and its weakest class, Powerful, was nearly indistinguishable from Joy without audio. A wrong angry tag on a neutral message is inside that error rate, and it then shapes how the bot treats the customer. Say that out loud before a store owner buys the feature.
I would keep the sliding window from the thesis: bound the history to the last N turns instead of since launch, and store derived counts rather than full transcripts where the product allows it, since the ablation says recent turns carry most of the signal. Key the profile by email as well as user ID, or resolve the email inside the eraser, because the person asking to be forgotten may never have had an account.
The class imbalance detail survives any model: the source counts Neutral outnumbering Sad roughly 4.5 to 1 in EmoryNLP, which is why weighted loss earned a thesis contribution and why your dashboard’s mood breakdown will lean boringly neutral too. If you’re wiring a chatbot into WordPress or WooCommerce and want the profile storage and the eraser plumbing built to match, that’s the kind of work I take on.