Previews using just the rest api?

Hi,

I am developing a site with elixir, so I cannot use any of your pre build libraries. Sadly I don't understand how to get the preview function working. The documentation always references your libraries.

Is there a simple explanation what to call in the api without integration of the api or the js toolbar?

Preferably with:

  1. You get the url with /preview/?....
  2. Fetch these parameters from the url
  3. Do these calls...

That would be super helpfull.

Thanks!

Hi @wishlephant,

Thanks for posting this question, and welcome to the Prismic community :slight_smile:

We're working on some more basic docs to explain how previewing works for use cases like yours. So, I'm happy that you asked, so I can test my own knowledge.

Here's how it works:

  • When you click the "preview" button in the editor, Prismic will:
    • set a cookie that includes the preview ref, and
    • send you to a predefined URL (your-site.com/preview by default)
  • Since Prismic has no visibility on the routing of your website, the next step is to determine the URL of the previewed document. So /preview can be a real page, or it can simply be a cloud function. This route has one job: determine the URL of the previewed document, and forward the user to that URL.
  • The /preview URL will be appended with some URL search params, including the ID of the document to preview. You can query the API for the preview of that document by extracting the ref from the preview cookie, and including that ref in your query. (See an explanation of refs, and see how the JavaScript kit handles this in Node.js and the browser.)
  • So, once you have received the document back from the API, you should have all of the information you need to construct a redirect URL using either the Route Resolver or a Link Resolver. Forward the user to the URL for the previewed document.
  • At the new URL, query the document using the ref from the preview cookie. You'll now see the document previewed.
  • To close the preview session, delete the cookie.

I hope this is helpful! Let me know if you have any questions.

Sam

Sorry, but I read through all of it and still don't understand any of it.

For example: I understand that I get the parameters through the URL, I have seen them here locally, but why do I need another cookie? And a redirect? Can't I just fetch the document via the api and display it right there? The redirect flow is also totally confusing. How do I build it if I don't use javascript?

Really need a barebone doc that goes through all of it and explains your domain knowledge of words and concepts that I haven't heared before :slight_smile:

@wishlephant I really like your suggestion for a barebones doc, and your questions are helping me to understand what that might look like. So, I'll offer more info — but please keep asking questions and for clarifications! I don't know anything about Elixir, so my explanations might be especially clumsy.

Why do I need another cookie?

To answer this question, first we need to talk about what a ref is.

Refs

Every time you query the API, you include a "ref" to specify which version of the content you want to query. The main purpose of the ref is to ensure you retrieve the latest version of your content. Content is cached (for speed) but refs are never cached. So, on every API query you make one request for a ref, and then you make a request for content using that ref. If the ref on the cached content is the same, you get the cached content. If the ref is different, you get refreshed content and the cache gets reloaded.

However, there's one exception: if you use a preview ref. The ref that you get from your preview cookie is a special ref that will ask the API for draft content.

The token in the URL

You have already seen that you can get your preview ref in the URL, and that works perfectly well. The only problem is that it isn't persistent. If you want to navigate on your site and stay in preview mode, you need to store the preview ref somewhere, and so we recommend using the cookie. (However, if you want to only use the URL parameter, that's fine.)

Using the cookie

You can access your cookies in JavaScript using document.cookie in the browser. That should reveal an encoded cookie called io.prismic.preview. Now you will need to do some string manipulation to extract the ref from the cookie string.

For one of my repos, the cookie looks like this:

'io.prismic.preview={%22_tracker%22:%22OiacoiRc%22%2C%22svelte-tutorial.prismic.io%22:{%22preview%22:%22https://svelte-tutorial.prismic.io/previews/YFs0pxIAACAAHh86:YTjMqhUAAGWT_Wc8?websitePreviewId=YJK_ghEAACMAE-o6%22}}'

The segment that I am interested in (which you have seen encoded in the URL) is this:

https://svelte-tutorial.prismic.io/previews/YFs0pxIAACAAHh86:YTjMqhUAAGWT_Wc8?websitePreviewId=YJK_ghEAACMAE-o6

Once I have extracted that, I need to encode is for my Rest API query. (All Rest API query parameters are encoded, as described in the Rest API Technical Reference.)

If I use JavaScript's built-in encodeURIComponent() function on that string, I get:

https%3A%2F%2Fsvelte-tutorial.prismic.io%2Fpreviews%2FYFs0pxIAACAAHh86%3AYTjMqhUAAGWT_Wc8%3FwebsitePreviewId%3DYJK_ghEAACMAE-o6

That is my preview ref. If you go to the API browser for that repo (svelte-tutorial.prismic.io/api/v2) you can copy-paste that ref into the ref box, and you'll see a third unpublished document (title "Test 2") appear in the results. To see the raw JSON, modify the URL in the address bar to include .cdn, as in

https://svelte-tutorial.cdn.prismic.io/api...

Why do you need a redirect?

If every page on your website takes the same format, or if your website only has one page, then you don't need a redirect. But, if you have multiple Custom Types in your repository that correspond to different page templates and different routes in your website, then you need a redirect.

For example, let's say your website has /blog/:uid and /product/:uid pages. If you open a "product" document called "hello world" in Prismic and click "preview", Prismic can't automatically direct you to /product/hello-world, because Prismic doesn't necessarily know your route structure.

So, we recommend creating a /preview route as an intermediary. When you launch the preview, Prismic sends all of the necessary info encoded in the URL to /preview, where you can parse the URL and make a quick API query to build the URL of the document you're trying to query. Then you can forward the user to that URL. You can do the forward in the browser using window.location.replace(newURL).

Exceptions to redirects

You might not need a redirect if:

You have a single-page app: If your app has no routes, you can probably set the preview route to the root of your website. When a user clicks the "preview" button, they'll go to the root of your app, and you can use the cookie and URL params to display the previewed content.

Your website only has one route structure: If every page on your app follows a consistent route structure and page template, like /:uid, then you might be able to get away with sending the user directly to that route. This will only work if the route is dynamic (it won't work if any of your routes are hard-coded), and it's not really recommended, because the previewing will break if you add other routes.

How do you build the redirect without JavaScript?

Short answer: I'm not sure. I would personally recommend building the redirect using client-side JavaScript (which will only run in the browser). I have a document in progress that explains how to do this, which I can share with you by DM if you want.

In principle, I think you can build the redirect on the server using Elixir. (Again, I don't know anything about Elixir, so this is a shot in the dark.) I imagine it will be a little more complicated. In essence:

  • The user clicks the preview button, and goes to your-site.com/preview&params
  • You receive a request to your server for your-site.com/preview&params, which will also include some cookies
  • You parse the params and the cookies as needed in your server-side script to construct a URL query with a preview ref
  • Using the data you get back from the Prismic API, you construct the URL for the document to preview
  • You send a 301 redirect response to the user, redirecting them to the URL of the previewed, draft document
  • The user follows that 301 and sends a new request to your server for the draft document
  • Your server receives a request for the previewed page, along with some cookies. You parse the cookies to get the preview ref and then construct your API query using that ref to get the documents you want to render for the user. With the API response, you build the page in Elixir and send it back to the user as a 200 response.

I hope this is clearer. It has certainly helped me to troubleshoot and clarify some of these steps for myself. Please do let me know if you have questions, comments, or issues.

Sam

1 Like

I can confirm you don't need any JS to support previewing. I've built a Ruby-based solution recently where, like Sam is saying, you just store the preview ref as a cookie, then redirect to the URL where you'd fetch a specific document, and you can use that cookie as the ref when you call the API to fetch the document. It sounds complicated at first but pretty simple to do in practice.

2 Likes

@samlittlefair thanks for the explanation. I would love to see that JS code of yours and hopefully now understand enough to build my own solution in elixir <3

Ah, now I understand.

https://example.com/preview?documentId=:document_id&token=:https_urls

Use the full url you get in the token param as token in this query:

https://platform.cdn.prismic.io/api/v2/documents/search?ref=:token

and see all the documents, limit to the document you got with :document_id and you have the document you need.

This is sooo simple, but the explanation you gave was way more complex :smiley: .

Hey @wishlephant,

I'm glad you figured it out! I'll send you that doc in a DM in any case. Let me know if you have any more questions :slight_smile:

Sam

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.