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

3 1

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

Image of Datadog

The Future of AI, LLMs, and Observability on Google Cloud

Datadog sat down with Google’s Director of AI to discuss the current and future states of AI, ML, and LLMs on Google Cloud. Discover 7 key insights for technical leaders, covering everything from upskilling teams to observability best practices

Learn More

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

Sentry blog image

How I fixed 20 seconds of lag for every user in just 20 minutes.

Our AI agent was running 10-20 seconds slower than it should, impacting both our own developers and our early adopters. See how I used Sentry Profiling to fix it in record time.

Read more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay