![Django Check SEO](https://user-images.githubusercontent.com/45763865/114545606-72178380-9c5c-11eb-99dd-1088bb2a0bd9.png) *Replacing some features of Yoast or SEMrush for Django & Django-CMS users.* In other words, django-check-seo will tell you if you have problems concerning a broad range of SEO aspects of your pages. [![PyPI](https://img.shields.io/pypi/v/django-check-seo?color=%232a2)](https://pypi.org/project/django-check-seo/) [![PyPI - Downloads](https://img.shields.io/pypi/dm/django-check-seo?color=%232a2)](https://pypi.org/project/django-check-seo/) [![GitHub last commit](https://img.shields.io/github/last-commit/kapt-labs/django-check-seo)](https://github.com/kapt-labs/django-check-seo) ---- # Requirements - Python 3.8+ & Django 2.2+ (*optional: django CMS 4+*) > *Still using Python 2? Version <0.6 [from this branch](https://github.com/kapt-labs/django-check-seo/tree/python2) is for you!* - Django Check SEO relies on [Django Site framework](https://docs.djangoproject.com/en/5.2/ref/contrib/sites/) + [permissions](https://docs.djangoproject.com/en/5.2/topics/auth/default/#permissions-and-authorization) - [beautifulsoup4](https://beautiful-soup-4.readthedocs.io/en/latest/) (>= 4.7.0) - [htmx](https://htmx.org/) (a version is included in Django Check SEO static files) # Install 1. Install the module from [PyPI](https://pypi.org/project/django-check-seo/): ``` python3 -m pip install django-check-seo ``` 2. Add it in your `INSTALLED_APPS`: ``` "django_check_seo", ``` 3. Add this in your `urls.py` *(add it before the `cms.urls` line if you're using django CMS)*: ``` path("django-check-seo/", include("django_check_seo.urls")), ``` 4. Update your Django Site objet with a working url (website url for prod env, localhost:8000 for your dev environment). 5. Add `testserver` to your `ALLOWED_HOSTS` (django-check-seo uses the Test Framework in order to get content, instead of doing a regular HTTP request). 6. Add the permission (`use_django_check_seo`) to the users/groups you want to let access Django Check SEO. 7. *(optional) Configure the settings (see [below](#settings) ).* 8. ![that's all folks!](https://i.imgur.com/o2Tcd2E.png) ---- # Misc This application may be used with or without [django CMS](https://www.django-cms.org/en/) (a "Check SEO" button will appear in the CMS toolbar if you're using django-cms). If you're not using Django CMS (only Django), here's the link format you need to use in order to access your pages reports (with or without using i18n): ``` https://example.com/django-check-seo/?page=/slug-of-page-to-check/ https://example.com/en/django-check-seo/?page=/slug-of-page-to-check/ ``` ---- # Settings ## Keywords handling ![**new in 2.0.0**](https://img.shields.io/badge/new_in-2.0.0-green) Keywords are discovered via a configurable function. Set its import path in your settings: ```py # This is the default if not set: read from html page (comma-separated) DJANGO_CHECK_SEO_KEYWORDS_DISCOVERY_METHOD = "django_check_seo.utils.keywords_discovery.meta_keywords" ``` To use keywords stored in the database (models `Page` and `Keyword` from Django Check SEO), set this instead: ```py DJANGO_CHECK_SEO_KEYWORDS_DISCOVERY_METHOD = "django_check_seo.utils.keywords_discovery.model_keywords" # Set/update keywords through Django Check SEO page: DJANGO_CHECK_SEO_KEYWORDS_EDITABLE = True ``` For **Django CMS** projects, you can use identification by CMS page id + language so that changing a page slug does not break the link to its keywords: ```py DJANGO_CHECK_SEO_KEYWORDS_DISCOVERY_METHOD = "django_check_seo.utils.keywords_discovery.django_cms_model_keywords" DJANGO_CHECK_SEO_KEYWORDS_EDITABLE = True ``` This method is **hybrid**: CMS pages are identified by `(cms_page_id, language)`; apphooks or other non-CMS URLs are still identified by path. On non-translated sites, `language` can be left empty or set to your single language code. **Django CMS edit and preview URLs**: When the URL you pass to Check SEO is a CMS edit or preview URL (e.g. `/en/admin/cms/placeholder/object/3/edit/372/`), django-check-seo detects it and either fetches the **draft** content (preview URL, using your session so no extra login) or the **published** page (by resolving to the public URL via PageContent/Page models). The result page shows whether the analysis is for the draft or the published page. Optional setting: `DJANGO_CHECK_SEO_CMS_EDIT_URL_TO_PUBLIC` (default `True`) to enable resolving edit/preview URLs to the public URL when not using draft. You're free to implement your own solution to handle keywords. ## Select main content (exclude header/footer/...) Since django-check-seo will count things like number of words on the main content and the number of internal links, it is important to only select the *main* content of the page (an address in the footer is not the main content of your page). Django-check-seo use a string (named `DJANGO_CHECK_SEO_EXCLUDE_CONTENT`) of [css selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors) to exclude unwanted html nodes from the html content: ```py DJANGO_CHECK_SEO_EXCLUDE_CONTENT = "tag, .class, #id, tag > .child_class" ``` > **Example**: See [this issue's comment](https://github.com/kapt-labs/django-check-seo/issues/35#issuecomment-593429870) for an example. > You can find a reference table of css selectors explained [here](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors#Reference_table_of_selectors) (on mdn docs). ## Basic config The basic config (used by default) is located in [`django-check-seo/conf/settings.py`](https://github.com/kapt-labs/django-check-seo/blob/master/django_check_seo/conf/settings.py#L5-L15) and looks like this: ```python DJANGO_CHECK_SEO_SETTINGS = { "content_words_number": [300, 600], "internal_links": 1, "external_links": 1, "meta_title_length": [30, 60], "meta_description_length": [50, 160], "keywords_in_first_words": 50, "max_link_depth": 3, "max_url_length": 70, } ``` If you need to change something, just define a dict named `DJANGO_CHECK_SEO_SETTINGS` in your settings.py. ### *Custom config example:* If you put this in your `settings.py` file: ```python DJANGO_CHECK_SEO_SETTINGS = { "internal_links": 25, "meta_title_length": [15,30], } ``` Then this will be the settings used by the application: ```python DJANGO_CHECK_SEO_SETTINGS = { "content_words_number": [300, 600], "internal_links": 25, # 1 if using default settings "external_links": 1, "meta_title_length": [15,30], # [30, 60] if using default settings "meta_description_length": [50, 160], "keywords_in_first_words": 50, "max_link_depth": 3, "max_url_length": 70, } ``` *Want to know more ? See the wiki page [Config explained](https://github.com/kapt-labs/django-check-seo/wiki/Config-explained).* ## Templates The `django_check_seo/default.html` template have an `