Get Involved
No items added to cart
No items added to cart
Adaptation of: https://voxel.guide/snippet/shortcode-to-display-common-words-from-reviews/
This snippet analyzes frequently used words and phrases from posts in the post_wall feed of the Voxel Timeline. It extracts common single words (unigrams) and two-word phrases (bigrams), filtering out generic stop words. The results are displayed as a tag-like word cloud using the [common_wall_words limit=”15″] shortcode.
The accompanying CSS ensures the words are visually appealing, arranged in a scrollable horizontal layout with soft gradient edges.
This is useful for highlighting popular discussion topics or trends from the post_wall feed, helping users quickly see the most talked-about subjects. 🚀
Use this snippet in Voxel's child theme functions.php file or via a Code Snippets plugin
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}function voxel_common_wall_words_shortcode( $atts ) {
global $wpdb, $post;// Set default shortcode attributes.
$atts = shortcode_atts(
[
'limit' => 10, // Maximum number of phrases to display.
],
$atts,
'common_wall_words'
);// Use the provided post_id or fallback to the current post.
$post_id = ! empty( $atts['post_id'] )
? intval( $atts['post_id'] )
: ( isset( $post->ID ) ? $post->ID : 0 );// Prepare the query to fetch wall posts.
$table_name = $wpdb->prefix . 'voxel_timeline';
$query = "SELECT content FROM $table_name WHERE feed = 'post_wall'";
if ( $post_id ) {
$query .= " AND post_id = $post_id";
}
$results = $wpdb->get_results( $query );// We count each unigram and bigram once per post.
$unigram_counts = [];
$bigram_counts = [];// Define an array of common stop words to exclude.
$stop_words = [
'the', 'and', 'a', 'an', 'to', 'of', 'in', 'it', 'is',
'that', 'this', 'i', 'for', 'on', 'with', 'as', 'was',
'but', 'are', 'be', 'by', 'not', 'have', 'had', 'or', 'at',
'from', 'you', 'your', 'they', 'we', 'which'
];// Process each post.
foreach ( $results as $result ) {
// Normalize post content.
$content = strtolower( strip_tags( $result->content ) );
// Remove punctuation (only allow letters, numbers, and whitespace).
$content = preg_replace( "/[^\w\s]/", '', $content );
// Split content into words.
$words = preg_split( '/\s+/', $content, -1, PREG_SPLIT_NO_EMPTY );
// Filter out stop words.
$filtered = array_filter( $words, function( $word ) use ( $stop_words ) {
return ! in_array( $word, $stop_words, true );
});
$filtered = array_values( $filtered ); // reindex// Get unique unigrams for this post.
$unique_unigrams = array_unique( $filtered );// Tally each unique unigram.
foreach ( $unique_unigrams as $uni ) {
if ( ! isset( $unigram_counts[ $uni ] ) ) {
$unigram_counts[ $uni ] = 0;
}
$unigram_counts[ $uni ]++;
}// Generate bigrams (two-word phrases) from the filtered words.
$bigrams = [];
$count_words = count( $filtered );
for ( $i = 0; $i < $count_words - 1; $i++ ) {
$bigram = $filtered[$i] . ' ' . $filtered[$i + 1];
$bigrams[] = $bigram;
}
// Get unique bigrams for this post.
$unique_bigrams = array_unique( $bigrams );// Tally each unique bigram.
foreach ( $unique_bigrams as $bi ) {
if ( ! isset( $bigram_counts[ $bi ] ) ) {
$bigram_counts[ $bi ] = 0;
}
$bigram_counts[ $bi ]++;
}
}// Filter out phrases that appear in only one post.
$unigram_counts = array_filter( $unigram_counts, function( $count ) {
return $count > 1;
});
$bigram_counts = array_filter( $bigram_counts, function( $count ) {
return $count > 1;
});// Remove unigrams that are part of any bigram in our final list.
foreach ( $bigram_counts as $bigram => $bcount ) {
$parts = explode( ' ', $bigram );
foreach ( $parts as $part ) {
if ( isset( $unigram_counts[ $part ] ) ) {
unset( $unigram_counts[ $part ] );
}
}
}// Merge bigrams and unigrams.
$merged = array_merge( $unigram_counts, $bigram_counts );// Sort by frequency in descending order.
arsort( $merged );// Limit to the specified count.
$merged = array_slice( $merged, 0, intval( $atts['limit'] ), true );// Build the output using a styled span.
$output = '';
foreach ( $merged as $phrase => $count ) {
$output .= '' . esc_html( $phrase ) . ' ';
}
$output .= '';
return $output;
}
add_shortcode( 'common_wall_words', 'voxel_common_wall_words_shortcode' );
add this to your custom css
.common-wall-words {
display: flex;
gap: 5px;
overflow-y: auto;
flex-direction: row;
justify-content: flex-start;
align-items: center;
padding-left: 10px;
}.common-wall-words span {
font-size: 0.775rem;
padding: 5px 20px;
border-radius: 90px;
border: 1px solid #DEDEDE;
white-space: nowrap;
display: inline-flex;
}.common-wall-words:before {
content: '';
position: absolute;
bottom: 0;
left: 0;
background: linear-gradient(to left, transparent, white);
height: 100%;
width: 15px;
}.common-wall-words:after {
content: '';
position: absolute;
bottom: 0;
right: 0;
background: linear-gradient(to right, transparent, white);
height: 100%;
width: 20px;
}
Are you sure you want to exit? Your current conversation will be lost.