Get Involved
No items added to cart
No items added to cart
This PHP snippet is an adaptation of Miguel’s code that is working for reviews. This one works for post_timeline .
Adaptation of: https://voxel.guide/snippet/shortcode-to-display-common-words-from-reviews/
It retrieves and analyzes frequently used words and phrases from posts in the post_timeline feed of the Voxel Timeline. It identifies common single words (unigrams) and two-word phrases (bigrams) while filtering out stop words. The results are displayed as a visually styled tag list using the [common_timeline_words limit=”15″] shortcode.
This is useful for highlighting popular topics or keywords from timeline posts. The CSS ensures the tags are neatly arranged in a scrollable row with a soft gradient effect at the edges.
Perfect for showcasing trending discussions or recurring themes in a community-driven WordPress site!
Use it in your child theme's functions.php file or code snippet plugin.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}function voxel_common_timeline_words_shortcode( $atts ) {
global $wpdb, $post;// Set default shortcode attributes.
$atts = shortcode_atts(
[
'limit' => 10, // Maximum number of phrases to display.
],
$atts,
'common_timeline_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 timeline posts from 'post_timeline' feed.
$table_name = $wpdb->prefix . 'voxel_timeline';
$query = $wpdb->prepare(
"SELECT content FROM $table_name WHERE feed = %s",
'post_timeline'
);if ( $post_id ) {
$query .= $wpdb->prepare(" AND post_id = %d", $post_id);
}$results = $wpdb->get_results( $query );
// Initialize arrays to store word frequencies.
$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 content.
foreach ( $results as $result ) {
// Normalize content.
$content = strtolower( strip_tags( $result->content ) );
$content = preg_replace( "/[^\w\s]/", '', $content );
$words = preg_split( '/\s+/', $content, -1, PREG_SPLIT_NO_EMPTY );// Filter out stop words.
$filtered = array_values( array_filter( $words, function( $word ) use ( $stop_words ) {
return ! in_array( $word, $stop_words, true );
}));// Get unique unigrams.
$unique_unigrams = array_unique( $filtered );// Count unigrams.
foreach ( $unique_unigrams as $uni ) {
if ( ! isset( $unigram_counts[ $uni ] ) ) {
$unigram_counts[ $uni ] = 0;
}
$unigram_counts[ $uni ]++;
}// Generate bigrams.
$bigrams = [];
$count_words = count( $filtered );
for ( $i = 0; $i < $count_words - 1; $i++ ) {
$bigram = $filtered[$i] . ' ' . $filtered[$i + 1];
$bigrams[] = $bigram;
}
$unique_bigrams = array_unique( $bigrams );// Count bigrams.
foreach ( $unique_bigrams as $bi ) {
if ( ! isset( $bigram_counts[ $bi ] ) ) {
$bigram_counts[ $bi ] = 0;
}
$bigram_counts[ $bi ]++;
}
}// Remove phrases appearing only once.
$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 appear in selected bigrams.
foreach ( $bigram_counts as $bigram => $bcount ) {
$parts = explode( ' ', $bigram );
foreach ( $parts as $part ) {
if ( isset( $unigram_counts[ $part ] ) ) {
unset( $unigram_counts[ $part ] );
}
}
}// Merge and sort by frequency.
$merged = array_merge( $unigram_counts, $bigram_counts );
arsort( $merged );// Limit results.
$merged = array_slice( $merged, 0, intval( $atts['limit'] ), true );// Build output.
$output = '';
foreach ( $merged as $phrase => $count ) {
$output .= '' . esc_html( $phrase ) . ' ';
}
$output .= '';
return $output;
}
add_shortcode( 'common_timeline_words', 'voxel_common_timeline_words_shortcode' );
add this to your custom css
.common-timeline-words {
display: flex;
gap: 5px;
overflow-y: auto;
flex-direction: row;
justify-content: flex-start;
align-items: center;
padding-left: 10px;
}.common-timeline-words span {
font-size: 0.775rem;
padding: 5px 20px;
border-radius: 90px;
border: 1px solid #DEDEDE;
white-space: nowrap;
display: inline-flex;
}.common-timeline-words:before {
content: '';
position: absolute;
bottom: 0;
left: 0;
background: linear-gradient(to left, transparent, white);
height: 100%;
width: 15px;
}.common-timeline-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.