Dev guideRecipesAPI ReferenceChangelog
Dev guideRecipesUser GuidesNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev guide

Modified and deleted content items

How to get content items based on last modified changes.

This article explains how to track content changes and deletions in Optimizely Graph. Use these queries to detect modified or deleted content items, determine when to regenerate a static site, or verify that a site has fully synced.

Note: Querying for deleted content requires HMAC authentication. Queries for modified content work with either HMAC or single key authentication.

Optimizely Graph lets you query for updates to content items. Use this to get snapshots of content items based on a datetime delta using the cursor. The total hit count indicates whether a site has fully synced.

You can get the first five modified documents updated since 2023-05-24T11:00 with this Optimizely Graph query:

{
  Content(
    limit: 5, 
    where: { _modified: { gte: "2023-05-24T11:00" } }
    orderBy: {_ranking: DOC}
  ) {
    total
    items {
      _modified
      ContentLink {
        GuidValue
      }
    }
  }
}

You can get all the modified documents updated since 2023-05-24T11:00 with this Optimizely Graph query using cursor:

{
  Content(
    limit: 5, 
    where: { _modified: { gte: "2023-05-24T11:00" } }
    orderBy: {_ranking: DOC}
    cursor: ""
  ) {
    total
    items {
      _modified
      ContentLink {
        GuidValue
      }
    }
    cursor
  }
}

You can get the next batches of the modified content by adding the cursor value to the cursor argument.

Deleted documents

You can query in Optimizely Graph for content items that were deleted. This is only possible by using HMAC authentication and adding the header cg-include-deleted with the value true. Each content item that is deleted will have the value of _modified updated and marked as deleted with _deleted: true.

With the single key, Optimizely only lets you retrieve published content items, so the _deleted values are null.

You can use the following Optimizely Graph query to get all modified content items, including deleted items, since 2023-05-20T11:00:

{
  Content(
    limit: 5, 
    where: { _modified: { gte: "2023-05-20T11:00" } }
    orderBy: {_ranking: DOC}
    cursor: ""
  ) {
    total
    items {
      _deleted
      ContentLink {
        GuidValue
      }
    }
    cursor
  }
}

You know that an item was deleted by looking at the _deleted value. When the value is true, the content was deleted. A response could look like the following and note that there are three deleted items in this batch.

{
  "data": {
    "Content": {
      "total": 13,
      "items": [
        {
          "_deleted": null,
          "ContentLink": {
            "GuidValue": "64ea99b4-fe38-43b7-a993-20ceb333861a"
          }
        },
        {
          "_deleted": true,
          "ContentLink": {
            "GuidValue": "c8ab68cf-7231-43ca-a376-ca4cac2e06d8"
          }
        },
        {
          "_deleted": null,
          "ContentLink": {
            "GuidValue": "582ecd34-e0bc-4d14-b467-8255b04d2b53"
          }
        },
        {
          "_deleted": true,
          "ContentLink": {
            "GuidValue": "c64c5afb-a538-4245-92d8-55625527cfd3"
          }
        },
        {
          "_deleted": true,
          "ContentLink": {
            "GuidValue": "4eaece75-3e53-440b-8dec-eb8d6d6895e0"
          }
        }
      ],
      "cursor": "FGluY2x1ZGVfY29udGV4dF91dWlkDnF1ZXJ5VGhlbkZldGNoAhZua3ZXUUFvMFRuU2plVUJmX1pfTlNnAAAAAAAADwQWTG5QWjFjRXFURnVpZktRd0d0MkZGQRZua3ZXUUFvMFRuU2plVUJmX1pfTlNnAAAAAAAADwUWTG5QWjFjRXFURnVpZktRd0d0MkZGQQ=="
    }
  },
  "extensions": {
    "correlationId": "92151285-aae3-4d7f-93e7-a009d390f18e",
    "cost": 9,
    "costSummary": [
      "Content(9) = limit(5) + fields(2) + basicFilter(1)*2"
    ]
  }
}

Query deleted content only

The cg-include-deleted-only header filters results so that only deleted items are returned. Use this header to build per-site wastebasket views that display only deleted content for a specific site.

This header is a modifier. Pair it with cg-include-deleted or cg-include-hard-deleted to control which type of deleted content is returned. All three headers require HMAC authentication.

The following table describes the header combinations and their behavior:

HeadersResult
cg-include-deleted: trueReturns active and soft-deleted content together
cg-include-deleted: true and cg-include-deleted-only: trueReturns only soft-deleted content
cg-include-hard-deleted: trueReturns active and hard-deleted content together
cg-include-hard-deleted: true and cg-include-deleted-only: trueReturns only hard-deleted content

Content deleted in any workflow status is included in the results. This applies to content that was in Draft, Ready to Publish, Scheduled for Publish, Rejected, Previously Published, or Published status at the time of deletion.

Note: When content is restored from trash, it continues to appear in deleted content results until the next indexing job runs. After that job completes, the restored content no longer appears.

Retrieve only soft-deleted content

Add the cg-include-deleted and cg-include-deleted-only headers to return only soft-deleted content items. The following query retrieves soft-deleted content modified after a specific date:

{
  Content(
    limit: 5, 
    where: { _modified: { gte: "2023-05-20T11:00" } }
    orderBy: {_ranking: DOC}
    cursor: ""
  ) {
    total
    items {
      _deleted
      _modified
      ContentLink {
        GuidValue
      }
    }
    cursor
  }
}

Send the request with both headers:

curl -X POST "https://cg.optimizely.com/content/v2" \
  -H "Authorization: epi-hmac APP_KEY:TIMESTAMP:NONCE:SIGNATURE" \
  -H "cg-include-deleted: true" \
  -H "cg-include-deleted-only: true" \
  -H "Content-Type: application/json" \
  -d '{"query": "{ Content(limit: 5, where: { _modified: { gte: \"2023-05-20T11:00\" } }, orderBy: {_ranking: DOC}, cursor: \"\") { total items { _deleted _modified ContentLink { GuidValue } } cursor } }"}'

Every item in the response has _deleted set to true because the cg-include-deleted-only header filters out all non-deleted content:

{
  "data": {
    "Content": {
      "total": 3,
      "items": [
        {
          "_deleted": true,
          "_modified": "2023-05-21T09:15:00Z",
          "ContentLink": {
            "GuidValue": "c8ab68cf-7231-43ca-a376-ca4cac2e06d8"
          }
        },
        {
          "_deleted": true,
          "_modified": "2023-05-22T14:30:00Z",
          "ContentLink": {
            "GuidValue": "c64c5afb-a538-4245-92d8-55625527cfd3"
          }
        },
        {
          "_deleted": true,
          "_modified": "2023-05-23T08:45:00Z",
          "ContentLink": {
            "GuidValue": "4eaece75-3e53-440b-8dec-eb8d6d6895e0"
          }
        }
      ],
      "cursor": "FGluY2x1ZGVfY29udGV4dF91dWlkDnF1ZXJ5VGhlbk..."
    }
  }
}

Retrieve only hard-deleted content

Replace cg-include-deleted with cg-include-hard-deleted to return only hard-deleted content items:

curl -X POST "https://cg.optimizely.com/content/v2" \
  -H "Authorization: epi-hmac APP_KEY:TIMESTAMP:NONCE:SIGNATURE" \
  -H "cg-include-hard-deleted: true" \
  -H "cg-include-deleted-only: true" \
  -H "Content-Type: application/json" \
  -d '{"query": "{ Content(limit: 5, orderBy: {_ranking: DOC}, cursor: \"\") { total items { _deleted ContentLink { GuidValue } } cursor } }"}'