v1 versioning in batch feeds

In your batch feeds, the version of an entity is determined through the dateModified field in the feed's envelope:

{
  "@context": "http://schema.googleapis.com",
  "dateModified": "2018-12-28T06:30:00:123-07:00",
  "@type": "DataFeed",
  "dataFeedElement": [
    /* All the items that are part of this feed go here */
  ]
}

All entities listed in the field dataFeedElement will have the same timestamp, as listed in the envelope.

For example, you could have the following feed with two entities:

{
  "@context": "http://schema.googleapis.com",
  "@type": "DataFeed",
  "dateModified": "2018-12-28T06:30:00:123-07:00",
  "dataFeedElement": [
    {
      "@type": "Restaurant",
      "@id": "http://www.provider.com/somerestaurant",
      ...
    },
    {
      "@type": "Menu",
      "@id": "http://www.provider.com/somerestaurant/menu/1"
      ...
    }
  ]
}

Both the menu and restaurant entities, once received and processed, would be individually versioned as "2018-12-28T06:30:00:123-07:00".

Versioning with incremental updates

When sending an entity using inventory updates, the version is set through the update_time field (in the case of an add/update call) or the delete_time field (in the case of a delete call). Since these fields are optional, the default timestamp is set to when Google received the call.

Example 1: update_time explicitly set

Suppose the following incremental call is received at 2018-12-28T06:30:10:123-07:00 for a completely new restaurant. Here's the HTTP POST request for that entity with ID "http://www.provider.com/somerestaurant", assuming the data feed uses the v1 inventory schema:

POST v2/apps/provider-project/entities/http%3A%2F%2Fwww.provider.com%2Fnewrestaurant:push
Host: actions.googleapis.com
Content-Type: application/ld+json

Below, the JSON payload body contains the update_time field. The entity with ID "http://www.provider.com/somerestaurant" results in this entity being versioned as 6:30:00 and not when it was received (ten seconds later at 6:30:10):

{
// This envelope is to be used for incremental.
  "entity": {
    // Note: "data" is not serialized as a string in our example for readability.
    "data": "[entity in JSON format serialized as a string]",
    "vertical": "FOODORDERING"
  },
  "update_time":"2018-12-28T06:30:00:123-07:00"
}

Example 2: update_time implicitly set

Suppose the following incremental call is received at 2018-12-28T06:30:10:123-07:00 for a completely new restaurant. Here's the HTTP POST request for that entity with ID "http://www.provider.com/somerestaurant", assuming the feed uses the v1 inventory schema:

POST v2/apps/provider-project/entities/http%3A%2F%2Fwww.provider.com%2Fnewrestaurant:push
Host: actions.googleapis.com
Content-Type: application/ld+json

Below, the JSON payload body does not contain the field update_time. The entity with ID "http://www.provider.com/somerestaurant" therefore results in this entity being versioned as 6:30:10:

{
// This envelope is to be used for incremental.
  "entity": {
    //Note: "data" is not serialized as a string in our example for readability.
    "data": "[entity in JSON format serialized as a string]",
    "vertical": "FOODORDERING"
  }
}

Versioning between batch and incremental

An entity sent to Google is processed and served only if it has the latest version. Note that entities sent through batch generally take a few days to get processed, whereas entities sent through the incremental API are processed immediately.

Best practices

  • Set the update_time and dateModified fields in incremental and batch, respectively, according to when the entity was modified in your systems.
  • If a batch feed (file) lists more than one top-level entity (for example, you pair your restaurants with services and menus), then update the timestamp as the data of an entity gets updated.
  • In incremental calls, we strongly recommend you explicitly set the update_time field.
  • It is imperative that once an incremental call is made, the corresponding feed timestamp (dateModified) is also updated before Google fetches it again.

Example

Google fetches the following file at 11 AM on 2018-12-28 for a completely new restaurant:

{
  "@context": "http://schema.googleapis.com",
  "@type": "DataFeed",
  "dateModified": "2018-12-28T06:30:00-07:00",
  "dataFeedElement": [
    {
      "@type": "Restaurant",
      "@id": "http://www.provider.com/newrestaurant",
      ...
    },
    {
      "@type": "Menu",
      "@id": "http://www.provider.com/newrestaurant/menu/1"
      ...
    }
    {
      "@type": "Service",
      "@id": "http://www.provider.com/newrestaurant/service/1"
      ...
    }
  ]
}

These entities get processed successfully and are versioned as "2018-12-28T06:30:00-07:00". Because batch feeds take time to process, these typically get served 2 days later.

At 1 PM, however, the partner's system has an update to the restaurant's phone number, which results in the following incremental call, which Google receives at 13:05 (5 seconds later):

POST v2/apps/provider-project/entities/http%3A%2F%2Fwww.provider.com%2Fnewrestaurant:push
Host: actions.googleapis.com
Content-Type: application/ld+json
{
// This envelope is to be used for incremental.
  "entity": {
    //Note: "data" is not serialized as a string in our example for readability.
    "data": "[entity in JSON format serialized as a string]",
    "vertical": "FOODORDERING"
  },
  "update_time":"2018-12-28T13:00:00-07:00"
}

The update_time is provided explicitly, and is greater (more recent) than the previous version (6:30 AM of the same day), so the restaurant entity is now versioned as "2018-12-28T13:00:00-07:00". However, the menu and service entities are still versioned as "2018-12-28T06:30:00-07:00".

There was an incremental call, so the batch feed gets updated with the new corresponding timestamp. Also, the corresponding changes are applied to the relevant entities (the restaurant entity has its phone number updated).

{
  "@context": "http://schema.googleapis.com",
  "@type": "DataFeed",
  "dateModified": "2018-12-28T13:00:00-07:00",
  "dataFeedElement": [
    {
      "@type": "Restaurant",
      "@id": "http://www.provider.com/newrestaurant",
      ...
    },
    {
      "@type": "Menu",
      "@id": "http://www.provider.com/newrestaurant/menu/1"
      ...
    }
    {
      "@type": "Service",
      "@id": "http://www.provider.com/newrestaurant/service/1"
      ...
    }
  ]
}

The next day (2018-12-29) at 11 PM, the feed gets fetched again. The restaurant still has the same version (1 PM of December 28), so this entity gets dropped and the current version is kept. However, the Menu and Service entities are updated with a new version.

Sitemap timestamps

The last-modified response header in the sitemap does not affect the version of an entity. It affects when the feed gets fetched by Google.

Best practices

  • Update the response header only when all files are up-to-date and ready to be fetched.
  • Explicitly use update_time and delete_time in incremental.
  • Set update_time, delete_time, and dateModified to when the data changes on your end.