Hook: mam_geodirectory_final_listings

Signature

apply_filters( 'mam_geodirectory_final_listings', array $dir_details );
Parameter Type Description
$dir_details array Full array of listing rows after every per-listing finaliser has run and the array has been sorted.

Returns: array — the (possibly modified) listings to send to the app. You must return an array.


Purpose

The last filter the directory pipeline runs before returning. By the time it fires, every listing has been:

  1. Pulled from the detail table (or supplied via Hook: mam_geodirectory_explcit_listings).
  2. Filtered by category, status, and authorship rules.
  3. Run through cache lookup.
  4. Enriched with category, marker, image, social, claim, and chat data.
  5. Sorted by title or distance (or sort_date for events).

This is the right place to make a global decision: cap the count, attach a header object, swap two listings’ positions, sprinkle ads, etc.


When it runs

return apply_filters( 'mam_geodirectory_final_listings', $dir_details );

End of mam_geodirectory_content::get_data_for_app(). Fires once per request, regardless of which content type triggered it. (Events-only mode runs local_app_sksort first, then this filter.)


Examples

Cap to top 100

add_filter( 'mam_geodirectory_final_listings', static fn( $listings ) => array_slice( $listings, 0, 100 ) );

Promote a specific listing to the top

add_filter( 'mam_geodirectory_final_listings', 'my_app_pin_top_listing' );

function my_app_pin_top_listing( $listings ) {
    $top_id = (int) get_option( 'my_app_pinned_listing_id' );
    if ( ! $top_id ) {
        return $listings;
    }
    $pinned = null;
    foreach ( $listings as $i => $listing ) {
        if ( (int) $listing['id'] === $top_id ) {
            $pinned = $listing;
            unset( $listings[ $i ] );
            break;
        }
    }
    if ( $pinned ) {
        array_unshift( $listings, $pinned );
    }
    return array_values( $listings );
}

Drop listings missing a thumbnail

add_filter( 'mam_geodirectory_final_listings', static fn( $listings ) => array_values( array_filter(
    $listings,
    static fn( $l ) => ! empty( $l['imageurl'] )
) ) );

Gotchas

  • Already includes derived fields. id, lat, lon, title, subcategories, marker_pin, imageurl, etc. — all the keys documented in Mobile listing data shape — are present. Don’t try to add raw post_id/latitude keys; the plugin has already removed them.
  • Filters after this run on the app side. The mobile client may further filter or sort. Any change here is the last server-side pass.
  • Order matters for performance. A callback that re-queries the database per listing kills request time. Cache aggressively.
  • The plugin runs mam_tab_manager per listing earlier in the pipeline. If you mutate tab_type or tab_location here, those changes don’t take effect — those keys are unset before this filter fires.
  • Always return an array. Returning a non-array breaks the directory response.

Verification

This article was last verified against:

  • Plugin: mam-geodirectory v2.1.5
  • Source: content-classes/local-app-geodirectory-v2-class.php (line 637)

Re-verify whenever the per-listing finaliser pipeline is restructured or the sort step moves to a different position.


  • Plugin: mam-geodirectory
  • Mobile listing data shape
  • Hook: mam_geodirectory_explcit_listings
  • Hook: mam_geodirectory_skip_record

Metadata

Field Value
Article type Hook Reference
Plugin slug mam-geodirectory
Applies to plugin version 2.1.5+
Category Extending MAM Suite
Hook type filter
Audience PHP developer
Last verified 2026-05-01
Contents

    Need Support?

    Can’t find the answer you’re looking for? Don’t worry we’re here to help!