@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¶ms
- You receive a request to your server for
your-site.com/preview¶ms
, 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