(get_post_ancestors == 2) is returning true on 1 as well?

Something is changing your results from get_ancestors() or something is changing your query which “changes” your child pages to grandchild pages when queried on the page. It also seems from comments that the post ID’s does not stay constant on the page.

What immediately catches my eye from your updated code is that your custom query is not resetted after you are done. You have to remember, the_post() sets the $post global to the current post being looped over in the loop, and once the loop is done, $post will hold the last post object of the loop.

You can add var_dump( $post ); before and after your current code and you will see that the value of $post differs. That is why you must always reset custom queries after you are done. Simply add wp_reset_postdata(); directly after endwhile just before endif. Doing a var_dump( $post ); now before and after the loop should render the same value.

$post is a global variable that is changed by many things, and bad code (like the code in your question) can change the $post global, which in turn returns wrong info, which in turn have you on a wild goose chase to find out why. A more reliable method is to use get_queried_object() to return the current page object. For an explanation, please feel free to check my question and the answer accepted answer from @gmazzap. Note, however this being reliable, query_posts breaks the main query object which holds the queried object.

I also note that you hardcode ID’s, do not do that. Every post/page have a post_parent property. If a post type is non-hierarchical, like posts, the post_parent value will always be 0 because non-hierarchical post types don’t have any hierarchy. Hierarchical post types like pages will either have 0 as post_parent if it is a top level page or have a numeric value if it is child/grandchild page, the value in post_parent will represent the ID of the page’s direct parent.

  • To correctly get the page id of a page being viewed, use get_queried_object()->ID or get_queried_object_id() instead of $post->ID.

  • To get the immediate post parent ID of the current page being viewed, use get_queried_object()->post_parent

  • To get the top level parent, use end( get_ancestors( get_queried_object()->ID, 'page' ) ). Remember, the top level parent will be the last ID in the array of ID’s returned by get_ancestors, the first ID will be the direct parent.

To rewrite your code, use something like this to get direct children of the page being viewed:

$page_object = get_queried_object();
// Check if page is top level or not and set $args accordingly
if ( $page_object->post_parent == 0 ) { // Top level page
    $parent_ID = (int) $page_object->ID;
} else { // Page is a child/grandchild page
    $parent_ID = (int) $page_object->post_parent;
}

// Setup query args
$args = [
    'post_parent' => $parent_ID,
    'post_type'   => 'page'
];
$q = new WP_Query( $args );
if ( $q->have_posts() ) {
    while ( $q->have_posts() ) {
    $q->the_post();

        // Run your code to display posts

    }
    wp_reset_postdata(); // EXTEMELY IMPORTANT!!!!!!!
}

To conclude, to determine the current hierarchy of a page, do the following

$current_page = get_queried_object();
if ( $current_page->post_parent == 0 ) {
    echo 'This is a parent';
} else {
    $hierarchy = get_ancestors( $current_page->ID, 'page' );
    $count = count( $hierarchy );
    $child = ( $count == 1 ) ? 'child' : 'grandchild';
    echo 'This is a ' . $child . ' page';
}

tech