DEV Community

Cover image for How to add unique meta tags in Django?
Magda Rosłaniec
Magda Rosłaniec

Posted on • Originally published at makneta.herokuapp.com

How to add unique meta tags in Django?

Today I'm going to continue the subject of meta tags. I'll be talking about two things:

1. what meta tags we need to create Twitter Cards

2. how to make meta tags unique for each article in Django

In my last article, I was writing about adding Open Graph to our meta tags to create Social Media Cards. http://makneta.herokuapp.com/post/what-are-metadata-and-meta-tags/ But to make sure that it will work on Twitter too, we should add a few more meta tags.

The tags that are required are twitter:card and twitter:title (or og:title).
If we want to display a big image with a title and description, we should set the content of twitter:card to “summary_large_image”

<meta name="twitter:card" content="summary_large_image" />

<meta name="twitter:title" content="Your title" />
Enter fullscreen mode Exit fullscreen mode

If we set content of twitter:card to “summary”, we will display the thumbnail image.

We can also add twitter:creator with our Twitter handle in content and twitter:site with the site’s Twitter handle

<meta name="twitter:creator" content="@your_handle" />

<meta name="twitter:site" content="@your_site_handle" />
Enter fullscreen mode Exit fullscreen mode

Those two are not required but specific for Twitter cards.

If we have Open Graph tags such as og:description, og:title, og:image, og:url, we don’t have to add them separately for Twitter.

If we want to make our meta tags work for SEO purposes, each article on our website should have a unique title, description, image and URL.

Because I learn the best in practice (and because I had wanted to have nice Social Media cards for ages), now it’s time to add open graph tags and Twitter tags to my Django blog.

First, let’s look at my Post model

class Post(models.Model):

   author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
   title = models.CharField(max_length=250)
   slug = models.SlugField(max_length=250, unique=True, default='', editable=False)
   header_image = models.ImageField(upload_to='blog', blank=True, null=True)
   image_alt = models.CharField(max_length=250, default="cover image", null=True)
   text = RichTextUploadingField(max_length=50000, blank=True, null=True)
   summary = models.TextField(blank=True, null=True)

   created_on = models.DateTimeField(auto_now_add=True)
   updated = models.DateTimeField(auto_now=True)
   status = models.IntegerField(choices=STATUS, default=0)
Enter fullscreen mode Exit fullscreen mode

I’m showing the Post model because in order to create unique cards for each blog post we need to use fields from the Post model.

In my meta tags, I’m using such fields as title, slug, header_image and summary. For most of them, it’s enough to use

{{object.field_name}}

.

<title>{{object.title}}</title>
<meta property="og:title" content="{{object.title}}">
<meta property="og:url" content="http://yourwebsite.com/{{object.slug}}" >
Enter fullscreen mode Exit fullscreen mode

Because my header_image field, as well as the summary field, are not mandatory, in order to avoid crashing the website I’m using some conditions.
If there is a summary, it should be used by meta tag description but if there isn’t a post summary (truncated to 160characters), it should take 160 characters from the blog article.

<meta property="og:description" content="{% if object.summary %}{{object.summary|striptags|truncatechars:160}}{% else %}
   {{object.text|safe|striptags|truncatechars:160}}{% endif %}">
Enter fullscreen mode Exit fullscreen mode

I don’t always add header images, sometimes I display my “universal” picture and I need to add the URL to an appropriate pic.

<meta property="og:image" content="{% if post.header_image %}http://yourwebsite.com{{ post.header_image.url }}
{% else %}http://yourwebsite.com{% static 'images/home-office.jpg' %}{% endif %}">
Enter fullscreen mode Exit fullscreen mode

Now all those tags together
We can forget about twitter:card tag

<meta name="twitter:card" content="summary_large_image" />
<title>{{object.title}}</title>
<meta property="og:title" content="{{object.title}}">
<meta property="og:url" content="http://yourwebsite.com/{{object.slug}}" >

<meta property="og:description" content="{% if object.summary %}{{object.summary|striptags|truncatechars:160}}{% else %}
   {{object.text|safe|striptags|truncatechars:160}}{% endif %}">

 <meta property="og:image" content="{% if post.header_image %}http://yourwebsite.com{{ post.header_image.url }}
   {% else %}http://yourwebsite.com{% static 'images/home-office.jpg' %}{% endif %}">

<meta name="twitter:card" content="summary_large_image" />
<title>{{object.title}}</title>

<meta name="twitter:creator" content="@your_handle" />

<meta name="twitter:site" content="@your_site_handle" />
Enter fullscreen mode Exit fullscreen mode

One more thing. If we leave meta tags like here, the description, title and image won’t work on the home page or the about page.
That’s why we need to wrap it in a condition like this:

{% if object.slug in request.path %}
<meta property="og:title" content="{{object.title}}">
<meta property="og:url" content="http://yourwebsite.com/{{object.slug}}" >

<meta property="og:description" content="{% if object.summary %}{{object.summary|striptags|truncatechars:160}}{% else %}
   {{object.text|safe|striptags|truncatechars:160}}{% endif %}">

 <meta property="og:image" content="{% if post.header_image %}{{ post.header_image.url }}
   {% else %}http://yourwebsite.com{% static 'images/home-office.jpg' %}{% endif %}">

<meta name="twitter:card" content="summary_large_image" />
<title>{{object.title}}</title>
{% else %}
<title>Your title</title>
   <meta property="og:title" content="Your title">
   <meta property="og:description" content="Description up to 160 characters">
   <meta property="og:image" content="http://image-url.png">
   <meta property="og:url" content="http://yourwebsite.com" >

   <meta name="twitter:card" content="summary_large_image" />   

{% endif %}
<meta name="twtter:site" content="@website_handle" />
<meta name="twtter:creator" content="@your_handle" />  
Enter fullscreen mode Exit fullscreen mode

This way my Twitter card from the previous post looks like that:
twitter card with laptop on a desk

Top comments (1)

Collapse
 
xarala221 profile image
Ousseynou Diop

Interesting article, Thank you for sharing.

In your meta url you hard coded the url, in Django you can use

{{ request.build_absolute_uri }}

to avoid that.

Thanks