Skip to content

Snippets / PHP

PHP CSS

Shortcode to display common words from Timeline

J Josi Schneider · 61 views · Updated 1 year ago
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' );
PHP · 126 lines
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;
}
CSS · 38 lines

Discussion

Ask a question or share how you used this.

Log in to join the discussion.

No comments yet — be the first.

Voxel Guide assistant
Ask about snippets, addons & how-tos

Hey — how can I help?

I can dig through the library for snippets, addons, and tutorials.

AI can be wrong — double-check anything important.