Django / Jinja
MarkdownSSR, script, signed-in customer and order detail integration for a store built with Django or Jinja templates.
This page is for stores built with Django or Jinja templates. The Django kit provided by the Sayproof team brings the server call, caching, failure handling and template helpers ready made. The kit is copied into the store project; it needs no package installation and uses only Django and Python’s standard library. It works with Python 3.9 and Django 2.2 and newer versions.
SSR or script
Section titled “SSR or script”The same template works with both methods; the only difference is the server key:
- SSR (recommended): When a server key is set, reviews are fetched on the server as ready HTML and are part of the page’s first response. Search engines see the review text and rating without waiting for the script; the script takes over the section once it loads. Details: Server-side rendering.
- Script: When no server key is set, an empty container is printed and the script fetches reviews in the browser. The server makes no call to Sayproof. To switch to SSR later, only the server key is added.
-
Copy the kit’s
sayprooffolder into your project’s app (for examplestore_app/sayproof/). The platform’s own folders are not changed; the kit is only added to your app. -
Define the settings:
SAYPROOF_BASE = os.environ.get("SAYPROOF_BASE", "")SAYPROOF_SITE_KEY = os.environ.get("SAYPROOF_SITE_KEY", "")SAYPROOF_SSR_KEY = os.environ.get("SAYPROOF_SSR_KEY", "")SAYPROOF_CHANNEL = os.environ.get("SAYPROOF_CHANNEL", "web")The Sayproof address, the Site key and the Channel code are shown with copy buttons in the Values for the setup list when Django / Jinja (on the server) is selected as the Setup route on the Integration › Showing reviews tab in the panel. The server key is not shown there; it is created on the Channels › Keys tab and appears only once, when it is created. The server key is kept only in the server’s environment variables; it is never written into a template or the browser.
-
Register the template helpers in the Jinja environment’s globals. If your settings file updates the globals with a dictionary (for example
GLOBAL_OPTIONS.update({...})), add these lines:GLOBAL_OPTIONS.update({"sayproof_ssr": "store_app.sayproof.markup.sayproof_ssr","sayproof_reviews": "store_app.sayproof.markup.sayproof_reviews","sayproof_script": "store_app.sayproof.markup.sayproof_script","sayproof_rating": "store_app.sayproof.markup.sayproof_rating","sayproof_json_ld": "store_app.sayproof.markup.sayproof_json_ld","sayproof_order_reviews": "store_app.sayproof.markup.sayproof_order_reviews",})Projects that set up their own Jinja environment add the
JINJA_GLOBALSdictionary to the environment’sglobals. In the Django template language the same names are used after{% load sayproof_tags %}.
Optional settings:
| Setting | Default | Use |
|---|---|---|
SAYPROOF_SERVER_BASE |
SAYPROOF_BASE |
When the server reaches Sayproof at a different address than the browser |
SAYPROOF_SCRIPT |
SAYPROOF_BASE + /storefront/sayproof.js |
When the script is served from a CDN |
SAYPROOF_TIMEOUT |
1.5 |
Timeout of the SSR call (seconds) |
SAYPROOF_VIEWER_TIMEOUT |
3 |
Timeout of the signed-in customer and order detail requests (seconds) |
SAYPROOF_CACHE_SECONDS |
60 |
How long an SSR response stays in the cache |
SAYPROOF_FAILURE_SECONDS |
10 |
How long to wait before trying again when Sayproof cannot be reached |
SAYPROOF_VIEWER_URL |
/sayproof/viewer/ |
Address of the signed-in customer endpoint |
SAYPROOF_CUSTOMER_EMAIL |
request.user.email |
Path of the function that reads the signed-in customer’s email address |
SAYPROOF_CUSTOMER_NAME |
(none) | Path of the function that reads the name shown next to a question; without it the question shows without a name (Signed-in customers › Questions and answers) |
Product page
Section titled “Product page”{% set reviews = sayproof_ssr(product.sku, product.name) %}{{ sayproof_reviews(product.sku, product.name, ssr=reviews) }}{{ sayproof_script() }}- The
sayproof_ssrresponse is fetched once and used for both the section and the structured data. The same product’s response comes from the cache for 60 seconds. - The product code must match the key in your product source and the line code in the order.
- To show reviews for all colours and sizes of a product together, pass the group code with
scope="group". sayproof_script()appears once on the page.- If you draw the review section with your own components, pass
headless=True; only the state tag is written into the container instead of HTML. See Headless.
Structured data
Section titled “Structured data”If the page already has the product’s Product JSON-LD, no second Product is added; the rating is added to the existing object:
{{ sayproof_json_ld(sayproof_rating(product_json_ld, reviews)) }}If the page has no Product JSON-LD:
{% if reviews %}{{ sayproof_json_ld(reviews.json_ld) }}{% endif %}sayproof_json_ld escapes customer texts so they cannot break out of the tag even if they contain </script>.
Signed-in customer
Section titled “Signed-in customer”- Connect the kit’s endpoint:
path("", include("store_app.sayproof.urls")). - Pass
viewer=Trueon the product page:sayproof_reviews(product.sku, product.name, ssr=reviews, viewer=True).
The customer’s state is not written into the page; the browser asks /sayproof/viewer/, and the store server forwards the question to Sayproof with the server key. The page stays cacheable. The email address is read from request.user.email by default; if the session information is elsewhere, define your own function with SAYPROOF_CUSTOMER_EMAIL. If the function returns an empty text, the customer is treated as anonymous and no call is made to Sayproof. Details: Signed-in customers.
Order detail page
Section titled “Order detail page”{{ sayproof_order_reviews(order.number, customer_email) }}{{ sayproof_script() }}If the order is not found in Sayproof or belongs to another customer, nothing is printed. This call is not cached.
Content Security Policy
Section titled “Content Security Policy”If the page uses a CSP nonce, pass the nonce parameter to sayproof_script, sayproof_reviews (with viewer=True) and sayproof_json_ld. script-src and connect-src must include the Sayproof address.
When something fails
Section titled “When something fails”- If the SSR call does not answer within 1.5 seconds or returns anything other than
200, the container is printed empty and the script fetches reviews in the browser. - The failure is kept in the cache for 10 seconds, so page loads do not wait again while Sayproof cannot be reached.
- The page does not break even if the cache is not working.
- Logs contain only the called path and the type of error; customer emails and keys are never logged.