Skip to content

First Payload

By the end of this page you will build an SEO payload, read its fields, and serialize it. Make sure easeo is installed first.

pip install easeo

Step 1: Configure the site

SEOConfig holds values that are the same for every page on your site. Two fields are required:

  • canonical_host: the hostname only, with no scheme and no path.
  • public_base_url: the absolute base URL used to resolve canonical paths.
from easeo import SEOConfig

config = SEOConfig(
    canonical_host="example.com",
    public_base_url="https://example.com",
    site_name="Example",
    title_template="{title} - Example",
)
const config = {
  canonicalHost: "example.com",
  publicBaseUrl: "https://example.com",
  siteName: "Example",
  titleTemplate: "{title} - Example",
};

Step 2: Describe the content

SEOEntity describes one piece of content. Only entity_type is required.

from easeo import SEOEntity

entity = SEOEntity(
    entity_type="post",
    title="Introducing easeo",
    excerpt="Deterministic SEO payloads for content platforms.",
)
const entity = {
  entityType: "post",
  title: "Introducing easeo",
  description: "Deterministic SEO payloads for content platforms.",
};

Valid entity types are: home, post, page, video, taxonomy, search, product, organization, local_business, faq, and other.

Step 3: Build the payload

The one function you need:

from easeo import build_seo_payload

payload = build_seo_payload(entity, "/blog/introducing-easeo", config)
const { buildSeoPayload } = require("@easeo/core");

const payload = buildSeoPayload(entity, "/blog/introducing-easeo", config);

Step 4: Read the result

print(payload.title)
# "Introducing easeo - Example"

print(payload.canonical)
# "https://example.com/blog/introducing-easeo"

print(payload.robots)
# "index,follow"

print(payload.og.type)
# "article"

print(payload.schema_jsonld["@type"])
# "Article"
console.log(payload.title);
// "Introducing easeo - Example"

console.log(payload.canonical);
// "https://example.com/blog/introducing-easeo"

console.log(payload.openGraph.type);
// "article"

console.log(payload.schemaJsonLd["@type"]);
// "Article"

Step 5: Serialize

payload.to_dict()      # canonical snake_case dict
payload.to_json()      # canonical JSON string
payload.toDict();          // canonical snake_case object
payload.toObject();        // camelCase object
JSON.stringify(payload);   // uses toObject()
payload.toJSONString();    // canonical JSON string

Determinism check

Building the same payload twice always yields the same bytes:

a = build_seo_payload(entity, "/blog/introducing-easeo", config)
b = build_seo_payload(entity, "/blog/introducing-easeo", config)

assert a == b
assert a.hash() == b.hash()
const a = buildSeoPayload(entity, "/blog/introducing-easeo", config);
const b = buildSeoPayload(entity, "/blog/introducing-easeo", config);

console.assert(a.equals(b));
console.assert(a.hash() === b.hash());

Recap

  • SEOConfig is site-wide; SEOEntity is per page.
  • build_seo_payload(entity, route, config) returns an SEOPayload.
  • The payload is structured, hashable, and serializable.

Next: Fallback and Overrides.