Waterfall Shoppable Stream Pinterest-Funnel
Curating more visual inspirations…
Shoppable Editorial
Your Curated Moodboard
Review inspiration & shoppable cart
Double-Tap Heart • Hotspot Tag Checkout • Curated Moodboard Drawer
Warm natural lighting, slatted oak wall joinery, hand-thrown ceramics, and ivory linen lounge modules.
Includes free white-glove spatial delivery
“The oak finish and ceramics matched the photo stream perfectly. Delivery was seamless.”
— Julian S., San FranciscoReview inspiration & shoppable cart
Double tap images in the stream or click ‘Save’ to curate your custom spatial lookbook.
Functions.php Snippet, WP REST API Endpoint & WooCommerce AJAX Hooks
Paste this snippet into your child theme’s functions.php to render the feed with [shoppable_waterfall_feed]:
function wpwf_register_waterfall_feed_shortcode($atts) {
wp_enqueue_script('wpwf-feed-core', get_stylesheet_directory_uri() . '/js/wpwf-feed.js', array(), '1.0.0', true);
wp_localize_script('wpwf-feed-core', 'wpwf_ajax', array(
'rest_url' => esc_url_raw(rest_url('wpwf/v1/pins')),
'nonce' => wp_create_nonce('wp_rest'),
'woo_cart' => esc_url_raw(wc_get_cart_url())
));
ob_start();
?>
<div class="wpwf-root" id="wpwf-stream-mount">
<div class="wpwf-masonry" id="wpwf-stream-container"></div>
<div id="wpwf-scroll-sentinel" class="text-center py-6">
<span class="wpwf-loader"></span>
</div>
</div>
<?php
return ob_get_clean();
}
add_shortcode('shoppable_waterfall_feed', 'wpwf_register_waterfall_feed_shortcode');
Registers the paginated REST API endpoint /wp-json/wpwf/v1/pins?page=1 reading from ACF or CPT:
add_action('rest_api_init', function () {
register_rest_route('wpwf/v1', '/pins', array(
'methods' => 'GET',
'callback' => 'wpwf_get_paginated_pins',
'permission_callback' => '__return_true'
));
});
function wpwf_get_paginated_pins(WP_REST_Request $request) {
$page = $request->get_param('page') ?: 1;
$query = new WP_Query(array(
'post_type' => 'shoppable_pin',
'posts_per_page' => 8,
'paged' => $page,
'post_status' => 'publish'
));
$results = array();
while ($query->have_posts()) {
$query->the_post();
$results[] = array(
'id' => get_the_ID(),
'title' => get_the_title(),
'img' => get_the_post_thumbnail_url(get_the_ID(), 'large'),
'hotspots' => get_field('hotspot_items'), // ACF Repeater
'products' => get_field('linked_woo_skus')
);
}
wp_reset_postdata();
return rest_ensure_response($results);
}
Handles instant AJAX Add-to-Cart without refreshing the visual stream:
add_action('wp_ajax_wpwf_ajax_add_to_cart', 'wpwf_handle_ajax_cart');
add_action('wp_ajax_nopriv_wpwf_ajax_add_to_cart', 'wpwf_handle_ajax_cart');
function wpwf_handle_ajax_cart() {
$product_id = absint($_POST['product_id']);
$quantity = 1;
$passed = apply_filters('woocommerce_add_to_cart_validation', true, $product_id, $quantity);
if ($passed && WC()->cart->add_to_cart($product_id, $quantity)) {
wp_send_json_success(array(
'cart_count' => WC()->cart->get_cart_contents_count(),
'cart_total' => WC()->cart->get_cart_total()
));
}
wp_send_json_error();
}