Creating embeds and bookmarks via Admin API

I’d like to add embeds (youtube, twitter) and bookmarks (some other sites) when creating posts through the API using ?source=html.

Is there a way to indicate to the parser that I’d like a link to be turned into an embed, rather than just presenting it as a normal link?

After having discovered that for public previews, although a post’s html includes a <!--members-only--> comment, adding such a comment when posting via html does not work. (I posted a clunky, but seemingly functional work-around here.)

My method would have been to embed a few things, get the html from the api, and use that as a model for creating a post in the first place, but because of my experience with the public preview, I thought I should ask for advice first!

I think this is one of the reasons why Ghost is switching text engine from Koenig to Lexical. Today with Koenig it is one block of content, Lexical seems to enable modifying elements using API within the content block, adding cards etc… In the Lexical playground this becomes more clear…

1 Like

There’s very little difference between mobiledoc and lexical in that regard, the underlying formats are different but functionally “cards” work very similarly in both editors.

There are two ways to insert cards:

1. Inside HTML with ?source=html

To create an embed via the HTML conversion you’d need to do something similar to what the editor itself does which is make an oembed API request to fetch the iframe HTML from the external embed source. Once you have that HTML you can put it in your HTML as an iframe:

<iframe src="${original embed url}">${fetched embed html}</iframe>

For bookmarks you’d need to do something similar and use metascraper or equivalent to fetch all of the necessary metadata and then build the bookmark card HTML manually using the same classes you see when Ghost renders a bookmark card on the front-end.

Ghost does have an endpoint for fetching embed/bookmark data at /ghost/api/admin/oembed/?url=${url to embed} that you can use to fetch the data ready for HTML creation. If you add an embed/bookmark card in the editor with your browser’s developer tools open you’ll be able to inspect the request and the data it gives you back.

2. Directly using the mobiledoc (original editor) / lexical (beta editor) formats

Here the process would be similar to the above with the requests to fetch the embed HTML or metadata from the external source but then you can add that data directly to a card payload in the source content. Downside to this approach is that it requires all of your content to be created in that format.

1 Like

Thank you @Kevin! This is almost working properly for me.

I am using this tweet as an example. I am using Ghost’s /oembed endpoint to get the html to put inside the iframe. I’m then using <iframe src="${url}">${embedHtml}</iframe> as you suggest and posting the following within my html.

<iframe src="">
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">A city steeped in history, offering glimpses of 🇮🇳&#39;s rich heritage and culture - <a href=";ref_src=twsrc%5Etfw">#Raipur</a>!<br><br>The bustling capital of <a href=";ref_src=twsrc%5Etfw">#Chhattisgarh</a> is geared up to host the 4th Framework Working Group Meeting. Through extensive deliberations, the <a href=";ref_src=twsrc%5Etfw">#G20India</a> delegates will aim to further promote… <a href=""></a></p>&mdash; G20 India (@g20org) <a href="">September 17, 2023</a></blockquote>\n<script async src="" charset="utf-8"></script>

Unfortunately, I get the sad document icon with “ refused to connect” when I view the post in Chrome.

But if I open the post in the editor, some processing takes place and it fixes things, and I can then click Update to have a working post. But I would like to do this all through the API if possible.

I’m not sure what I’m doing wrong here. Any suggestions?