Contentful logo

Contentful Community

Embed Youtube or Vimeo video directly into Rich Text Content Type

Is it possible to embed a Youtube or Vimeo video directly into the Rich Text Content Type? If not, what is the best practice for allowing a user of Contentful to add videos to blog posts for example.

Thanks!

Hi @james.barber,

You could, for example, create a content type called Video that has a field URL where the uses inserts the URL of a Youtube or Video video. After that you need to write a rich text renderer in your front-end application that prints out the necessary embed HTML code for respective video platform.

I.e. you would be embedding the Video content type to another content type that has a Rich Text field.

Thanks for that! Your example inspired the solution I came to. Instead of creating a seperate Content Type the user just needs to add a hyperlink of the video’s embed url.

Now in my blog post template file I check my hyperlinks and if one includes youtube.com/embed (or player.vimeo.com/video from Vimeo embeds - I imagine these checks could possible be better) return an iframe with the embed URL.

import { INLINES } from '@contentful/rich-text-types'
import { documentToReactComponents } from '@contentful/rich-text-react-renderer'

export const query = graphql`
  query {
    contentfulResource {
      resourceContent {
        json
      }
   }
}`

const Post = (props) => {
  const options = {
    renderNode: {
      [INLINES.HYPERLINK]: (node) => {
        if((node.data.uri).includes("player.vimeo.com/video")){
          return <IframeContainer><iframe title="Unique Title 001" src={node.data.uri} frameBorder="0" allowFullScreen></iframe></IframeContainer>
        } else if((node.data.uri).includes("youtube.com/embed")) {
          return <IframeContainer><iframe title="Unique Title 002" src={node.data.uri} allow="accelerometer; encrypted-media; gyroscope; picture-in-picture" frameBorder="0" allowFullScreen></iframe></IframeContainer>
        }
      }
    }
  }

 return(
  <div>
     {documentToReactComponents(props.data.contentfulResource.resourceContent.json, options)}
  </div>
 )
}

export default Post

The <IframeContainer> is a component created to ensure the iframes retain their aspect ratio and are responsive. Bonus code below.

const IframeContainer = styled.span`
  padding-bottom: 56.25%; 
  position: relative; 
  display: block; 
  width: 100%;

  > iframe {
    height: 100%;
    width: 100%;
    position: absolute; 
    top: 0; 
    left: 0;
  }`

I’m using styled-components but you can re create this by replacing <IframeContainer> with <span class="ClassNameToReplaceIframeContainer"> (the reason it’s a span is to adhere to best practice as these iframes will be rendered within p tags)

If something here doesn’t make sense let me know :slightly_smiling_face:

Cheers!

3 Likes

@james.barber Glad to hear I was able to help! :slight_smile:

Yeah, your implementation is certainly better and simpler if you only need to embed the video and no additional data is needed.

I also found an easy way to do this whilst still accomating links that might not be from YT. See below :slight_smile:.

[INLINES.HYPERLINK]: (node) => {
				if (node.data.uri.indexOf('youtube.com') !== -1) {
					return (
						<div className={styles.videoHolder}>
							<iframe
								id="ytplayer"
								src={node.data.uri}
								type="text/html"
								width="640"
								height="360"
								frameBorder="0"
								allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture ; fullscreen"
							/>
						</div>
					);
				} else
					return (
						<a
							href={node.data.uri}
							target={`${node.data.uri.startsWith(website_url) ? '_self' : '_blank'}`}
							rel={`${node.data.uri.startsWith(website_url) ? '' : 'noopener noreferrer'}`}
						>
							{node.content[0].value}
						</a>
					);
			} 

The above is embedded to const options

and displayed in {documentToReactComponents(json, options)}

Hope this helps!

Hi everyone,

While this question has been solved, I wanted to point out an alternative solution that can help enable content reusability and provide authors with more editing flexibility over things like the video thumbnail. I wrote about this here:

Let me know if I can help further or answer any questions. :slightly_smiling_face:

-Connor