I'm building two metabox galleries on the same page with the help of a tutorial. The code works fine. However the galleries are automatically displayed after the content on the front end. What I would like to do is to display each gallery wherever I want in my template page, not automatically after the content. Here is the PHP code in my functions.php: /** * Sortable WordPress Gallery class to create gallery metabox and save it */ class Sortable_WordPress_Gallery { /** * Unique ID of the metabox * @var string */ protected $id; /** * Metabox Title * @var string */ protected $title = ''; /** * Metabox Context * @var string */ protected $context = 'advanced'; /** * Metabox Priority * @var string */ protected $priority = 'high'; /** * Hook into the appropriate actions when the class is constructed. */ public function __construct( $id, $title = '', $context = 'advanced', $priority = 'high' ) { // ID is required if( $id == '' ) { return; } $this->id = $id; // Create title from ID if not provided if( $title == '' ) { $this->title = ucfirst( $id ); } else { $this->title = $title; } // Only valid context can be changed $available_context = array( 'advanced', 'side', 'normal'); if( in_array( $context, $available_context ) ) { $this->context = $context; } // Only valid priorty can be changed $available_priority = array( 'default', 'high', 'low'); if( in_array( $priority, $available_priority ) ) { $this->priority = $priority; } add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) ); add_action( 'save_post', array( $this, 'save' ) ); add_filter( 'the_content', array( $this, 'render' ) ); } /** * Adds the meta box container. */ public function add_meta_box( $post_type ) { // Limit meta box to certain post types. // Can be extended using filter 'sortable_wordpress_gallery_post_types' or // using a dynamic filter 'sortable_wordpress_gallery_METABOX-ID_post_types' $post_types = apply_filters( 'sortable_wordpress_gallery_post_types', array( 'page' ) ); $post_types = apply_filters( 'sortable_wordpress_gallery_' . $this->id . '_post_types', $post_types ); if ( in_array( $post_type, $post_types ) ) { add_meta_box( $this->id, $this->title, array( $this, 'render_meta_box_content' ), $post_type, $this->context, $this->priority ); } } /** * Render Meta Box content. * * @param WP_Post $post The post object. */ public function render_meta_box_content( $post ) { // Add an nonce field so we can check when saving wp_nonce_field( $this->id . '_metabox', $this->id . '_metabox_nonce' ); // Get the gallery saved data $sortable_gallery = get_post_meta( $post->ID, '_' . $this->id . '_sortable_wordpress_gallery', true ); ?> <table class="table"> <tr> <th style="vertical-align: top;"> <?php _e( 'Slider Images', 'your_text_domain' ); ?> </th> <td> <!-- Creating a dynamic ID using the metabox ID for JavaScript--> <ul id="<?php echo $this->id; ?>_sortable_wordpress_gallery" class="sortable_wordpress_gallery"> <?php // Getting all the image IDs by creating an array from string ( 1,3,5 => array( 1, 3, 5) ) $gallery = explode(",", $sortable_gallery ); // If there is any ID, create the image for it if( count( $gallery ) > 0 && $gallery[0] != '' ) { foreach ( $gallery as $attachment_id ) { // Create a LI elememnt $output = '<li tabindex="0" role="checkbox" aria-label="' . get_the_title( $attachment_id ) . '" aria-checked="true" data-id="' . $attachment_id . '" class="attachment save-ready selected details">'; // Create a container for the image. (Copied from the WP Media Library Modal to use the same styling) $output .= '<div class="attachment-preview js--select-attachment type-image subtype-jpeg portrait">'; $output .= '<div class="thumbnail">'; $output .= '<div class="centered">'; // Get the URL to that image thumbnail $output .= '<img src="' . wp_get_attachment_thumb_url( $attachment_id ) . '" draggable="false" alt="">'; $output .= '</div>'; $output .= '</div>'; $output .= '</div>'; // Add the button to remove this image if wanted (we set the data-gallery to target the correct gallery if there are more than one) $output .= '<button type="button" data-gallery="#' . $this->id . '_sortable_wordpress_gallery" class="button-link check remove-sortable-wordpress-gallery-image" tabindex="0"><span class="media-modal-icon"></span><span class="screen-reader-text">Deselect</span></button>'; $output .= '</li>'; echo $output; } } ?> </ul> <!-- Hidden input used to save the gallery image IDs into the database --> <!-- We are also creating dynamic IDs here so that we can easily target them in JavaScript --> <input type="hidden" id="<?php echo $this->id; ?>_sortable_wordpress_gallery_input" name="_<?php echo $this->id; ?>_sortable_wordpress_gallery" value="<?php echo $sortable_gallery; ?>" /> <!-- Button used to open the WordPress Media Library Modal --> <button type="button" class="button button-primary add-sortable-wordpress-gallery" data-gallery="#<?php echo $this->id; ?>_sortable_wordpress_gallery"><?php _e( 'Add Images', 'your_text_domain' ); ?></button> </td> </tr> </table> <?php } /** * Save the meta when the post is saved. * * @param int $post_id The ID of the post being saved. */ public function save( $post_id ) { /* * We need to verify this came from the our screen and with proper authorization, * because save_post can be triggered at other times. */ // Check if our nonce is set. if ( ! isset( $_POST[ $this->id . '_metabox_nonce'] ) ) { return $post_id; } $nonce = $_POST[ $this->id . '_metabox_nonce']; // Verify that the nonce is valid. if ( ! wp_verify_nonce( $nonce, $this->id . '_metabox' ) ) { return $post_id; } /* * If this is an autosave, our form has not been submitted, * so we don't want to do anything. */ if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return $post_id; } // Check the user's permissions. if ( 'page' == $_POST['post_type'] ) { if ( ! current_user_can( 'edit_page', $post_id ) ) { return $post_id; } } else { if ( ! current_user_can( 'edit_post', $post_id ) ) { return $post_id; } } /* OK, it's safe for us to save the data now. */ $gallery = sanitize_text_field( $_POST[ '_' . $this->id . '_sortable_wordpress_gallery' ] ); // Update the meta field. update_post_meta( $post_id, '_' . $this->id . '_sortable_wordpress_gallery', $gallery ); } /** * Rendering the gallery */ public function render( $content ) { global $post; // Get our registered post types $post_types = apply_filters( 'sortable_wordpress_gallery_post_types', array( 'page' ) ); $post_types = apply_filters( 'sortable_wordpress_gallery_' . $this->id . '_post_types', $post_types ); // Get current post type $this_post_type = get_post_type( $post ); // If the current post type is also a registered post type, create the gallery if( in_array( $this_post_type, $post_types ) ) { // Get all the image IDs $gallery_images = get_post_meta( $post->ID, '_' . $this->id . '_sortable_wordpress_gallery', true ); if( $gallery_images != '' ) { // If the data retrieved is not empty, create an array $gallery_images_array = explode( ',', $gallery_images ); //Create a gallery container with the 3 column layout $content .= '<div class="gallery" style="display: flex;">'; // For each image ID, create the gallery image foreach ( $gallery_images_array as $image_id ) { $html = wp_get_attachment_image( $image_id ); if( $html == '' ) { continue; } $content .= '<div class="gallery-item">'; $content .= '<a href="' . get_permalink( $image_id ) . '" target="_blank">'; $content .= $html; $content .= '</a>'; $content .= '</div>'; } $content .= '</div>'; } } return $content; } } /** * WordPress Gallery Factory */ class Sortable_WordPress_Galleries { /** * Gallery Defaults * @var array */ protected $gallery_defaults = array( 'class' => 'Sortable_WordPress_Gallery', 'id' => '', 'title' => '', 'context' => '', 'priority' => '' ); /** * Galleries that have been registered to use * @var array */ protected $galleries = array(); /** * Loaded galleries (Gallery objects) * @var array */ protected $loaded_galleries = array(); /** * Constructor method */ public function __construct() { add_action( 'init', array( $this, 'collect_galleries') ); add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) ); add_action( 'admin_init', array( $this, 'create_galleries' ) ); add_filter( 'the_content', array( $this, 'render_galleries' ) ); } /** * Enqueuing admin scripts and styles */ /* public function admin_scripts() { wp_enqueue_script( 'sortable-gallery-admin-js', plugin_dir_url( __FILE__ ). 'admin.js', array( 'jquery' ) ); wp_enqueue_style( 'sortable-gallery-admin-css', plugin_dir_url( __FILE__ ). 'admin.css' ); }*/ public function admin_scripts() { wp_enqueue_script( 'sortable-gallery-admin-js', get_template_directory_uri() . '/gallery-multiple-metabox/js/admin.js', array( 'jquery' ) ); wp_enqueue_style( 'sortable-gallery-admin-css', get_template_directory_uri() . '/gallery-multiple-metabox/css/admin.css' ); } /** * Collect galleries passed to our filter */ public function collect_galleries() { $this->galleries = apply_filters( 'sortable_wordpress_galleries', $this->galleries ); } /** * Hook our method load_galleries on edit post screens */ public function create_galleries() { add_action( 'load-post.php', array( $this, 'load_galleries' ) ); add_action( 'load-post-new.php', array( $this, 'load_galleries' ) ); } /** * Create gallery objects to create metaboxes */ public function load_galleries() { foreach ( $this->galleries as $gallery ) { $gallery = wp_parse_args( $gallery, $this->gallery_defaults ); $class = $gallery['class']; if( $class != '' ) { $this->loaded_galleries[] = new $class( $gallery['id'], $gallery['title'], $gallery['context'], $gallery['priority'] ); } } } /** * Load all the galleries and render each gallery */ public function render_galleries($content) { $this->load_galleries(); foreach ( $this->loaded_galleries as $gallery ) { $content = $gallery->render( $content ); } return $content; } } new Sortable_WordPress_Galleries(); add_filter( 'sortable_wordpress_galleries', 'add_sortable_gallery' ); function add_sortable_gallery( $galleries ) { // Gallery metabox #1 $galleries[] = array( 'class' => 'Sortable_WordPress_Gallery', 'id' => 'post-metabox', 'title' => 'Sortable Gallery' ); // Gallery metabox #2 $galleries[] = array( 'class' => 'Sortable_WordPress_Gallery', 'id' => 'post-metabox-2', 'title' => 'Sortable Gallery-2' ); return $galleries; } I'm struggling to find the way to render the gallery out of `the_content();` and insert the rendering code inside my template. Thank you.