{"id":2341,"date":"2026-10-20T08:32:18","date_gmt":"2026-10-20T07:32:18","guid":{"rendered":"https:\/\/wpgeodirectory.com\/documentation\/article\/add-featured-image-to-listing-php\/"},"modified":"2026-10-20T08:39:39","modified_gmt":"2026-10-20T07:39:39","slug":"add-featured-image-to-listing-php","status":"publish","type":"gd_place","link":"https:\/\/wpgeodirectory.com\/documentation\/article\/code-snippets\/add-featured-image-to-listing-php\/","title":{"rendered":"How to add a featured image to a listing with PHP"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">GeoDirectory keeps listing images in its own attachments table, so calling <code>set_post_thumbnail()<\/code> on its own doesn&#8217;t add the image to the listing&#8217;s gallery. Save the images through the listing&#8217;s <code>post_images<\/code> field instead. GeoDirectory then imports the file, adds it to the gallery, and sets the first image as both the GeoDirectory featured image and the WordPress post thumbnail.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How the post_images value works<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><code>post_images<\/code> is a string of images separated by <code>::<\/code>. Each image is <code>url|attachment_id|title|caption<\/code>. A new image only needs its URL. The first image in the string becomes the featured image.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Add a new featured image and keep the existing gallery<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This snippet puts a new image first and keeps the images the listing already has after it:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-php\">\/**\n * Make an image the featured image of a GeoDirectory listing.\n *\n * @param int    $post_id   Listing ID.\n * @param string $image_url Full URL of the image to import.\n *\/\nfunction my_gd_set_featured_image( $post_id, $image_url ) {\n\t\/\/ Current images as &quot;url|id|title|caption::url|id|title|caption&quot;.\n\t$current = GeoDir_Media::get_field_edit_string( $post_id, &#039;post_images&#039; );\n\n\t$images = esc_url_raw( $image_url );\n\tif ( $current ) {\n\t\t$images .= &#039;::&#039; . $current;\n\t}\n\n\twp_update_post(\n\t\tarray(\n\t\t\t&#039;ID&#039;          =&gt; $post_id,\n\t\t\t&#039;post_images&#039; =&gt; $images,\n\t\t)\n\t);\n}\n\n\/\/ Example.\nmy_gd_set_featured_image( 123, &#039;https:\/\/example.com\/wp-content\/uploads\/photo.jpg&#039; );<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">To replace the whole gallery, pass only the new URLs, separated by <code>::<\/code>, with the featured image first. Images that were in the gallery but are missing from the new string are deleted.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When you create a listing with <code>wp_insert_post()<\/code>, you can pass <code>post_images<\/code> in the same array as the title and content.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Things to check<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The image URL must be reachable from your server, because GeoDirectory downloads it.<\/li>\n\n\n\n<li>The new featured image is saved in the uploads folder for the listing&#8217;s publish date, not the current month. WordPress does this when it sideloads an image for an existing post.<\/li>\n\n\n\n<li>Old images that already exist on the listing keep their files. Only their order changes.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">If you&#8217;re importing a lot of listings, the CSV import may be easier. See <a href=\"https:\/\/wpgeodirectory.com\/documentation\/article\/how-tos\/how-to-format-the-csv-file-for-importing-listing-images\/\">How to format the CSV file for importing listing images<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>GeoDirectory keeps listing images in its own attachments table, so calling set_post_thumbnail() on its own doesn&#8217;t add the image to the listing&#8217;s gallery. Save the images through the listing&#8217;s post_images field instead. GeoDirectory then imports the file, adds it to the gallery, and sets the first image as both the GeoDirectory featured image and the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"article\/tags":[],"article\/categories":[211,433],"class_list":["post-2341","gd_place","type-gd_place","status-publish","hentry","gd_placecategory-tips-tricks-more","gd_placecategory-code-snippets"],"_links":{"self":[{"href":"https:\/\/wpgeodirectory.com\/documentation\/wp-json\/wp\/v2\/article\/2341","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wpgeodirectory.com\/documentation\/wp-json\/wp\/v2\/article"}],"about":[{"href":"https:\/\/wpgeodirectory.com\/documentation\/wp-json\/wp\/v2\/types\/gd_place"}],"author":[{"embeddable":true,"href":"https:\/\/wpgeodirectory.com\/documentation\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wpgeodirectory.com\/documentation\/wp-json\/wp\/v2\/comments?post=2341"}],"version-history":[{"count":1,"href":"https:\/\/wpgeodirectory.com\/documentation\/wp-json\/wp\/v2\/article\/2341\/revisions"}],"predecessor-version":[{"id":2402,"href":"https:\/\/wpgeodirectory.com\/documentation\/wp-json\/wp\/v2\/article\/2341\/revisions\/2402"}],"wp:attachment":[{"href":"https:\/\/wpgeodirectory.com\/documentation\/wp-json\/wp\/v2\/media?parent=2341"}],"wp:term":[{"taxonomy":"gd_place_tags","embeddable":true,"href":"https:\/\/wpgeodirectory.com\/documentation\/wp-json\/wp\/v2\/article\/tags?post=2341"},{"taxonomy":"gd_placecategory","embeddable":true,"href":"https:\/\/wpgeodirectory.com\/documentation\/wp-json\/wp\/v2\/article\/categories?post=2341"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}