CMS Content Models: Structure and Implementation

These are the types returned by the Content Management API, as defined in its GraphQL schema. Fields used only internally, such as A/B test bookkeeping, are left out.

Page

type Page {
    id: ID!
    revisionId: ID
    title: String!
    handle: String!
    description: String
    status: String!
    sections(after: String, before: String, first: Int, last: Int): SectionConnection!
    sectionOverrides: JSON
    sectionsWithUnpublishedOverrides: [ID!]!
    hasUnpublishedChanges: Boolean!
    seo: SEO!
    template: Template
    publishedAt: DateTime
    firstPublishedAt: DateTime
    firstPublishedAtTimezone: String
    createdAt: DateTime
    updatedAt: DateTime
    locale: Locale
}

Page History

Returned by the pageHistory query.

type PageRevisionConnection {
    edges: [PageRevisionEdge!]!
    nodes: [PageRevision!]!
    pageInfo: PageInfo!
    totalCount: Int
}

type PageRevisionEdge {
    cursor: String!
    node: PageRevision!
}

Page Revision

type PageRevision {
    id: ID!
    pageId: String!
    title: String!
    handle: String!
    description: String
    status: String!
    sections: [Section]
    sectionOrder: [ID]
    seo: SEO!
    user: User
    storeId: String!
    publishedAt: DateTime
    firstPublishedAt: DateTime
    firstPublishedAtTimezone: String
    createdAt: DateTime
    sectionOverrides: JSON
}

Page Info

Pagination info on connections. Content release lists use ContentReleasePageInfo, whose cursors can be null.

type PageInfo {
    hasNextPage: Boolean!
    hasPreviousPage: Boolean!
    startCursor: String!
    endCursor: String!
}

Blog

type Blog {
    id: ID!
    title: String!
    handle: String!
    description: String
    status: String!
    articles(after: String, before: String, first: Int, last: Int): ArticleConnection!
    sections(after: String, before: String, first: Int, last: Int): SectionConnection!
    sectionOverrides: JSON
    hasUnpublishedChanges: Boolean!
    seo: SEO!
    template: Template
    publishedAt: DateTime
    firstPublishedAt: DateTime
    firstPublishedAtTimezone: String
    createdAt: DateTime
    updatedAt: DateTime
    locale: Locale
}

Article

type Article {
    id: ID!
    title: String!
    handle: String!
    status: String!
    blogId: ID
    blog: Blog
    template: Template
    description: String
    author: String
    category: String
    tags: [String]
    excerpt: String
    bodyHtml: String
    sections(after: String, before: String, first: Int, last: Int): SectionConnection!
    sectionOverrides: JSON
    hasUnpublishedChanges: Boolean!
    seo: SEO!
    publishedAt: DateTime
    firstPublishedAt: DateTime
    firstPublishedAtTimezone: String
    createdAt: DateTime
    updatedAt: DateTime
    locale: Locale
}

Product Page

type ProductPage {
    id: ID!
    title: String!
    handle: String!
    description: String
    status: String!
    sections(after: String, before: String, first: Int, last: Int): SectionConnection!
    sectionOverrides: JSON
    hasUnpublishedChanges: Boolean!
    seo: SEO!
    template: Template
    sourceProduct: Product // null when the page has no linked or synced Shopify product
    publishedAt: DateTime
    firstPublishedAt: DateTime
    firstPublishedAtTimezone: String
    createdAt: DateTime
    updatedAt: DateTime
    locale: Locale
}

Product Page History

Returned by the productPageHistory query.

type ProductPageRevisionConnection {
    edges: [ProductPageEdge!]!
    nodes: [ProductPageRevision!]!
    pageInfo: PageInfo!
    totalCount: Int
}

Product Page Revision

type ProductPageRevision {
    id: ID!
    productId: String!
    title: String!
    handle: String!
    description: String
    status: String!
    sections: [Section]
    sectionOrder: [ID]
    seo: SEO!
    user: User
    publishedAt: DateTime
    firstPublishedAt: DateTime
    firstPublishedAtTimezone: String
    storeId: String!
    createdAt: DateTime
    sectionOverrides: JSON
}

Product Status

The status of a Shopify product, returned on sourceProduct.data.status.

enum ProductStatus {
    ACTIVE
    ARCHIVED
    DRAFT
    UNLISTED // active, but only reachable by direct link
}

Collection

type CollectionPage {
    id: ID!
    title: String!
    handle: String!
    description: String
    status: String!
    sections(after: String, before: String, first: Int, last: Int): SectionConnection!
    sectionOverrides: JSON
    hasUnpublishedChanges: Boolean!
    seo: SEO!
    template: Template
    sourceCollection: ShopifyCollection // null when the page has no linked or synced Shopify collection
    publishedAt: DateTime
    firstPublishedAt: DateTime
    firstPublishedAtTimezone: String
    createdAt: DateTime
    updatedAt: DateTime
    locale: Locale
}

Section

A section's data holds its field values. Its shape comes from the section's schema; see the Section Schema API.

type SectionConnection {
    edges: [SectionEdge!]!
    nodes: [Section!]!
    pageInfo: PageInfo!
    totalCount: Int
}

type SectionEdge {
    cursor: String!
    node: Section!
}

type Section {
    id: ID!
    revisionId: ID
    parentContentType: ContentType
    title: String!
    status: String!
    data: JSON // the section's field values, shaped by its section schema
    dataSource: JSON
    styles: JSON
    hasReferences: Boolean
    referencesCount: Int
    publishedAt: DateTime
    createdAt: DateTime
    updatedAt: DateTime
    locale: Locale
}

Template

type Template {
    id: ID!
    title: String!
    type: String!
    isDefault: Boolean!
    status: String!
    sections(after: String, before: String, first: Int, last: Int): SectionConnection!
    publishedAt: DateTime
    storeId: String!
    createdAt: DateTime
    updatedAt: DateTime
    disjunctive: Boolean
    rules: [TemplateRule]
    locale: Locale
}

type TemplateRule {
    id: ID!
    templateId: String!
    attribute: String!
    operator: String!
    value: String!
    createdAt: DateTime
    updatedAt: DateTime
}

Site Settings

type SiteSettings {
    id: ID!
    revisionId: ID
    status: String!
    settings: JSON
    seo: SEO!
    favicon: String
    publishedAt: DateTime
    createdAt: DateTime
    updatedAt: DateTime
    locale: Locale
}

Schedule

type Schedule {
    id: ID!
    title: String!
    description: String
    executeAt: DateTime
    timezone: String
    state: ScheduleState!
    totalContentCount: Int!
    content: [Content!]
    createdAt: DateTime
    updatedAt: DateTime
}

enum ScheduleState {
    created
    succeeded
    scheduled
    queued
    running
    failed
}

Content Release

type ContentRelease {
    id: ID!
    name: String!
    handle: String!
    status: ContentReleaseStatus!
    description: String
    publishedAt: DateTime
    archivedAt: DateTime
    createdAt: DateTime
    updatedAt: DateTime
    scheduledPublishAt: DateTime
    scheduleTimezone: String
    scheduleOverwriteConflicts: Boolean
    drafts: [ContentReleaseDraftEntry!]!
    conflicts: [ContentReleaseConflict!]!
}

enum ContentReleaseStatus {
    open
    publishing
    published
    archived
}

enum ContentReleaseDraftType {
    page
    article
    blog
    product
    collection
    siteSettings
    section
    template
}

type ContentReleaseDraftEntry {
    contentType: ContentReleaseDraftType!
    contentId: ID!
    draftId: ID!
    baseVersion: Int
    title: String
    handle: String
    contentHandle: String
    updatedAt: DateTime
    updatedByUserName: String
    hasContentChanges: Boolean! // false when publishing leaves this content unchanged
    affectedLocations: [ContentReleaseAffectedLocation!]!
    affectedLocationsTruncated: Boolean!
}

type ContentReleaseAffectedLocation {
    contentType: ContentReleaseDraftType!
    contentId: ID!
    title: String
    handle: String
    locale: Locale // null when the content has no locale
}

type ContentReleaseConflict {
    contentType: String!
    contentId: ID!
    baseVersion: Int!
    currentVersion: Int!
    currentUpdatedAt: DateTime
    currentUpdatedByUserName: String
    changes: [ContentReleaseConflictChange!]! // computed only when requested
}

type ContentReleaseConflictChange {
    field: String!
    path: String!
    changeType: String!
    valueType: String!
    liveValue: JSON
    draftValue: JSON
    baseValue: JSON // the value the draft's edit was recorded against; site settings drafts only, otherwise null
    conflicting: Boolean // true when publishing overwrites a live edit here; null wherever baseValue is always null
}

type ContentReleaseConnection {
    edges: [ContentReleaseEdge!]!
    nodes: [ContentRelease!]!
    pageInfo: ContentReleasePageInfo!
    totalCount: Int!
}

type ContentReleaseEdge {
    cursor: String!
    node: ContentRelease!
}

type ContentReleasePageInfo {
    hasNextPage: Boolean!
    hasPreviousPage: Boolean!
    startCursor: String
    endCursor: String
}

Event

An entry in the store's change journal, returned by the events query.

type Event {
    id: ID!
    storeId: ID!
    contentEnvironmentId: ID
    releaseId: ID
    type: String! // <subject>.<action>, e.g. content.page.published
    subjectType: String!
    subjectId: ID!
    actorUserId: ID
    occurredAt: DateTime!
    data: JSON
}

Content Environment

type ContentEnvironment {
    id: ID!
    name: String!
    handle: String!
    storeId: String!
    createdAt: DateTime!
}

Locale

A storefront locale. Localized content carries its locale; see Localization.

type Locale {
    id: ID!
    languageCode: String!
    countryCode: String
    isPrimary: Boolean
    active: Boolean
    createdAt: DateTime
    updatedAt: DateTime
    fallbackLocale: FallbackLocale
    isFallbackLocale: Boolean
}

type FallbackLocale {
    id: ID!
    languageCode: String!
    countryCode: String
}

User

type User {
    id: String!
    first_name: String
    last_name: String
    email: String!
    avatar_url: String
}

SEO

type SEO {
    title: String
    description: String
    image: String
    keywords: [String!]
    noIndex: Boolean
    noFollow: Boolean
}

Was this page helpful?