Registers a Custom Post Type A hidden post type (snn_like) is created to store like counts.
Retrieves or Creates a Like Record When a like button is clicked, the system checks if a record for the given identifier exists.
If not, it creates one and initializes the like count to zero.
Handles Like Requests via REST API A custom REST API endpoint (snn/v1/like) is registered to process like
The SNN Like Button Shortcode [snn_like_button identifier="your_unique_identifier"] generates a simple thumbs-up button that allows users to like a specific item (e.g., a post, product, or any unique entity).
By the way this will work fine for any wordpress theme or builder ..etc doesnt matter the system.
/**
* SNN Like Button Shortcode
*
* This code registers a hidden custom post type for storing like counts,
* sets up a REST API endpoint to handle AJAX like requests,
* and defines a shortcode [snn_like_button identifier="your_unique_identifier"]
* that outputs a thumbs‑up button.
*
* Place this code in your theme’s functions.php file.
*/
/* ============================================================================
1. Register Custom Post Type for Storing Likes
============================================================================ */
add_action( 'init', 'snn_register_like_post_type' );
function snn_register_like_post_type() {
$args = [
'public' => false,
'show_ui' => false,
'capability_type' => 'post',
'supports' => [ 'title' ],
];
register_post_type( 'snn_like', $args );
}
/* ============================================================================
2. Helper Functions to Retrieve/Create a Like Record and Get the Count
============================================================================ */
/**
* Retrieve (or create) the like record (post) for a given identifier.
*
* @param string $identifier Sanitized identifier.
* @return WP_Post|false
*/
function snn_get_like_post( $identifier ) {
// Try to find the post by its slug.
$post = get_page_by_path( $identifier, OBJECT, 'snn_like' );
if ( ! $post ) {
// Create a new post if not found.
$post_id = wp_insert_post( [
'post_title' => $identifier,
'post_name' => $identifier,
'post_type' => 'snn_like',
'post_status' => 'private',
] );
if ( ! is_wp_error( $post_id ) ) {
$post = get_post( $post_id );
update_post_meta( $post->ID, '_snn_like_count', 0 );
update_post_meta( $post->ID, '_snn_like_ips', [] );
}
}
return $post;
}
/**
* Get the current like count for a given identifier.
*
* @param string $identifier
* @return int
*/
function snn_get_like_count( $identifier ) {
$post = snn_get_like_post( $identifier );
$count = get_post_meta( $post->ID, '_snn_like_count', true );
return $count ? intval( $count ) : 0;
}
/* ============================================================================
3. REST API Endpoint to Handle Like Requests
============================================================================ */
add_action( 'rest_api_init', function() {
register_rest_route( 'snn/v1', '/like', [
'methods' => 'POST',
'callback' => 'snn_handle_like',
'permission_callback' => '__return_true',
] );
} );
function snn_handle_like( WP_REST_Request $request ) {
// Sanitize and validate the identifier.
$identifier = $request->get_param( 'identifier' );
$identifier = sanitize_key( $identifier );
if ( empty( $identifier ) ) {
return new WP_Error( 'no_identifier', 'No identifier provided', [ 'status' => 400 ] );
}
// Get the visitor’s IP address.
$user_ip = $_SERVER['REMOTE_ADDR'];
// Retrieve (or create) the like record.
$post = snn_get_like_post( $identifier );
if ( ! $post ) {
return new WP_Error( 'post_error', 'Could not create like record', [ 'status' => 500 ] );
}
// Retrieve saved IPs for this like.
$ips = get_post_meta( $post->ID, '_snn_like_ips', true );
if ( ! is_array( $ips ) ) {
$ips = [];
}
// If this IP already liked this identifier, do nothing.
if ( in_array( $user_ip, $ips, true ) ) {
return rest_ensure_response( [
'count' => intval( get_post_meta( $post->ID, '_snn_like_count', true ) )
] );
}
// Increment the like count.
$count = intval( get_post_meta( $post->ID, '_snn_like_count', true ) );
$count++;
update_post_meta( $post->ID, '_snn_like_count', $count );
// Save the IP.
$ips[] = $user_ip;
update_post_meta( $post->ID, '_snn_like_ips', $ips );
return rest_ensure_response( [ 'count' => $count ] );
}
/* ============================================================================
4. Shortcode to Output the Like Button
============================================================================ */
/**
* Shortcode: [snn_like_button identifier="your_unique_identifier"]
*
* @param array $atts Shortcode attributes.
* @return string HTML for the like button.
*/
function snn_like_button_shortcode( $atts ) {
$atts = shortcode_atts( [
'identifier' => '',
], $atts, 'snn_like_button' );
$identifier = sanitize_key( $atts['identifier'] );
if ( empty( $identifier ) ) {
return 'Identifier missing';
}
$like_count = snn_get_like_count( $identifier );
$button = '<button class="snn-like-button" data-identifier="' . esc_attr( $identifier ) . '" onclick="snn_likeButton(this)">👍' . esc_html( $like_count ) . '</button>';
return $button;
}
add_shortcode( 'snn_like_button', 'snn_like_button_shortcode' );
/* ============================================================================
5. Inline JavaScript for AJAX Handling (No External JS File)
============================================================================ */
add_action( 'wp_footer', 'snn_inline_like_script' );
function snn_inline_like_script() {
?>
<script type="text/javascript">
// Define the global object with the REST API endpoint and nonce.
var snnLike = {
endpoint: "<?php echo esc_url( rest_url( 'snn/v1/like' ) ); ?>",
nonce: "<?php echo wp_create_nonce( 'wp_rest' ); ?>"
};
function snn_likeButton(el) {
var identifier = el.getAttribute('data-identifier');
// Prevent multiple rapid clicks.
if ( el.getAttribute('data-processing') === 'true' ) {
return;
}
el.setAttribute('data-processing', 'true');
var xhr = new XMLHttpRequest();
xhr.open("POST", snnLike.endpoint, true);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.onload = function() {
if ( xhr.status >= 200 && xhr.status < 300 ) {
var response = JSON.parse(xhr.responseText);
if ( response.count !== undefined ) {
el.innerHTML = '👍' + response.count;
}
}
el.removeAttribute('data-processing');
};
xhr.onerror = function() {
el.removeAttribute('data-processing');
};
xhr.send(JSON.stringify({ identifier: identifier, nonce: snnLike.nonce }));
}
</script>
<?php
}