Cookbook/Pricing

From GoodRelations Wiki
Jump to: navigation, search

Modeling Price Information

The GoodRelations Cookbook
Recipe Pricing
Description Modeling Price Information: Quantity discounts, seasonal discounts, price ranges, pricing variants, and compound prices
Status draft
Level advanced
Tags pricing, prices, rebates, discounts

This page describes how the GoodRelations ontology for e-commerce can be used to model price information. Such can be embedded using the W3C RDFa syntax into Web pages and will be crawled and used by next generation Web search engines.

One of the design principles of GoodRelations (*) is that

  • simple things should be simple to express, while
  • complex things should be possible to model without tweaking or extending the vocabulary.


On this page, we demonstrate how the established GoodRelations elements can be used to expose fine-granular price information like

"We lease our boats for 24 USD per 6 hours for 0-3 days, and for 75 USD per day for any longer rental."

(*) Wikiquote attributes this principle to Alan Kay.

Exposing GoodRelations rich meta-data can be as simple as this:

Minimal Example: Turtle Syntax

@prefix gr: <http://purl.org/goodrelations/v1#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

:company a gr:BusinessEntity;
    gr:legalName "Hepp Space Ventures Inc."@en;
    gr:offers :offering.

:offering a gr:Offering;
    rdfs:label "Volkswagen Station Wagon, 4WD, 400 $"@en;
    rdfs:comment "I sell my old Volkswagen Station Wagon, 4WD, for 400 $"@en;
    gr:hasBusinessFunction gr:Sell;
    gr:hasPriceSpecification
        [ a gr:UnitPriceSpecification;
          gr:hasCurrencyValue "400"^^xsd:float;
          gr:hasCurrency "USD"^^xsd:string. ].

Minimal Example: RDFa Syntax

<div xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
       xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
       xmlns="http://www.w3.org/1999/xhtml"
       xmlns:gr="http://purl.org/goodrelations/v1#"
       xmlns:xsd="http://www.w3.org/2001/XMLSchema#">
   <div  about="#company" typeof="gr:BusinessEntity">
    <div property="gr:legalName" content="Hepp Space Ventures Inc." xml:lang="en"></div>
    <div rel="gr:offers">
     <div about="#offering" typeof="gr:Offering">
      <div property="rdfs:comment" content="I sell my old Volkswagen Station
 Wagon, 4WD, for 400 $" xml:lang="en"></div>
      <div rel="gr:hasBusinessFunction"
             resource="http://purl.org/goodrelations/v1#Sell"></div>
      <div rel="gr:hasPriceSpecification">
         <div typeof="gr:UnitPriceSpecification">
          <div property="gr:hasCurrency" content="USD" datatype="xsd:string"></div>
          <div property="gr:hasCurrencyValue" content="400" datatype="xsd:float"></div>
         </div>
      </div>
      <div property="rdfs:label" content="Volkswagen Station Wagon, 4WD, 400 $" xml:lang="en"></div>
     </div>
    </div>
   </div>
</div>

But when you have more fine-grained data available on your end, you will likely expose that full level of detail on the Web.

Preliminaries

RDFa and Microdata Examples

The examples below are all in Turtle syntax, which is more human-readable and easier to maintain than RDFa or Microdata. You can always get an RDFa or Microdata variant of a code example using the free tool at

Prefixes

First, we have to define the prefixes used in the examples:

@prefix foo: <http://www.example.com/xyz#> .
@prefix gr: <http://purl.org/goodrelations/v1#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

Simple Offer

Next, let's model a simple offer to sell potatoes.

# Offer to sell potatoes

foo:company a gr:BusinessEntity ;
    gr:legalName "Hepp Space Ventures, Inc."@en ;
    gr:offers foo:offer.

foo:offer a gr:Offering ;
    rdfs:label "Potatoes for sale"@en ;
    rdfs:comment "We sell potatoes"@en ;
    gr:hasBusinessFunction gr:Sell ;
    gr:validFrom "2010-05-01T00:00:00Z"^^xsd:dateTime ;
    gr:validThrough "2010-12-31T23:59:59Z"^^xsd:dateTime ;
    gr:hasPriceSpecification foo:price.

Note: The actual object being offered (i.e. the potatoes) can (and should) be described in more detail. See the other GoodRelations recipes for examples. This recipe focuses on modeling the pricing.

Pricing

Example: 1 USD per piece

The UN/CEFACT Common Code for "piece" or "item" is "C62".

# 1 USD per piece (= per potatoe)
foo:price a gr:UnitPriceSpecification ;
    gr:hasCurrency "USD"^^xsd:string ;
    gr:hasCurrencyValue "1.0"^^xsd:float ;
    gr:hasUnitOfMeasurement "C62"^^xsd:string ;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean .

Example: 4 USD per kilogram

The UN/CEFACT Common Code for "kilogram" is "KGM" .

# 4 USD per kilogram
foo:price a gr:UnitPriceSpecification ;
    gr:hasCurrency "USD"^^xsd:string ;
    gr:hasCurrencyValue "4.0"^^xsd:float ;
    gr:hasUnitOfMeasurement "KGM"^^xsd:string ;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean .

Example: Price given in per liter, kg, meter, ...

There are two different ways of modeling this, and both are supported by GoodRelations:

1. You can e.g. say that you offer salt or red wine and that the price is USD 1 per 10 g or 1 l.

2. You can say that you offer exactly 10g of salt or 1 l of red wine, but maybe accept this offer multiple times.

In case, you model it using gr:hasUnitOfMeasurement attached to the gr:UnitPriceSpecification.

Example: 1 l of Bordeaux red wine for 1 USD/liter

foo:offer a gr:Offering;
    gr:hasBusinessFunction gr:Sell;
    gr:includesObject [ a gr:TypeAndQuantityNode;
                        gr:amountOfThisGood "1"^^xsd:float;
                        gr:hasUnitOfMeasurement "C62"^^xsd:string;
                        gr:typeOfGood foo:redwine ];
    gr:hasPriceSpecification [
        a gr:UnitPriceSpecification;
        gr:hasCurrency "USD"^^xsd:string;
        gr:hasCurrencyValue "1.00"^^xsd:float;
        gr:validThrough "2012-12-31T23:59:59Z"^^xsd:dateTime;
        gr:hasUnitOfMeasurement "LTR"^^xsd:string ].

# This represents an arbitrary amount of red wine:
foo:redwine a gr:SomeItems, <http://www.productontology.org/id/Bordeaux_wine>;
    gr:name "ACME Bordeaux Red Wine - dry and tasty"@en.

This approach works only if the price is related to a standard unit (C62, INH, LTR, GRM, ...). So you can say that the price is 1 USD / liter (unit code: LTR), but this way, you cannot say that it is 1 USD per 10 gram or per ten liters.

If you want to say something like "USD 1 per 10 g", you must

  • create a gr:SomeItems node representing some objects / some amount of the good,
  • add this to a gr:Offering with gr:includesObject and a gr:TypeAndQuantityNode with 10 g as the quantity
  • set the price to 1 USD per 1 piece (code for piece:C62) of this offer (because one piece of this gr:SomeItems instance means 10 g).

Example: Table salt for 1 USD / 10 g

foo:offer a gr:Offering;
    gr:hasBusinessFunction gr:Sell;
    gr:includesObject [ a gr:TypeAndQuantityNode;
                        gr:amountOfThisGood "10"^^xsd:float;
                        gr:hasUnitOfMeasurement "GRM"^^xsd:string;
                        gr:typeOfGood foo:salt ];
    gr:hasPriceSpecification [
        a gr:UnitPriceSpecification;
        gr:hasCurrency "USD"^^xsd:string;
        gr:hasCurrencyValue "1.00"^^xsd:float;
        gr:validThrough "2012-12-31T23:59:59Z"^^xsd:dateTime;
        gr:hasUnitOfMeasurement "C62"^^xsd:string ].

# This represents an arbitrary amount of table salt:
foo:redwine a gr:SomeItems, <http://www.productontology.org/id/Salt>;
    gr:name "ACME Table Salt - clear and salty"@en.

Quantity Discounts

Case 1: The price per unit is reduced for ADDITIONAL items beyond a certain minimum quantity

Example: Something costs 4 USD per kilogram up to 5 kilogram, 3 USD for any quantity beyond that. If you buy 9 kilogram, you will have to pay

  • 5 kg * 4 USD for the first 5 kg PLUS
  • 4 kg * 3 USD for the additional 4 kg

The total will be 32 USD.

GoodRelations pattern: Simply attach multiple instances of gr:UnitPriceSpecification to the gr:Offering and constrain their validity using non-overlapping gr:hasEligibleQuantity and gr:hasUnitOfMeasurement properties, i.e., two unit price specifications, one for 0..5 kg, and one for everything beyond 5 kg. Since there is no way to indicate "greater than", we have to use "5.00000001"^^xsd:float in the example below.

# 4 USD per kilogram up to 5 kilogram, 3 USD for any quantity beyond that
foo:price1 a gr:UnitPriceSpecification  ;
    gr:hasCurrency "USD"^^xsd:string ;
    gr:hasCurrencyValue "4.0"^^xsd:float ;
    gr:hasUnitOfMeasurement "KGM"^^xsd:string ;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean ;
    gr:hasEligibleQuantity [ a gr:QuantitativeValue ;
                            gr:hasUnitOfMeasurement "KGM"^^xsd:string ;
                            gr:hasMinValue "0"^^xsd:float ;
                            gr:hasMaxValue "5"^^xsd:float ].

foo:price2 a gr:UnitPriceSpecification ;
    gr:hasCurrency "USD"^^xsd:string ;
    gr:hasCurrencyValue "3.0"^^xsd:float ;
    gr:hasUnitOfMeasurement "KGM"^^xsd:string ;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean ;
    gr:hasEligibleQuantity [ a gr:QuantitativeValue ;
                            gr:hasUnitOfMeasurement "KGM"^^xsd:string ;
                            gr:hasMinValue "5.00000001"^^xsd:float ].


You have to link from the offering to both price specifications now. Simply change

  • gr:hasPriceSpecification foo:price.

to

  • gr:hasPriceSpecification foo:price1, foo:price2.

So the offer node will look as follows:

foo:offer a gr:Offering;
    gr:includes foo:potatoes;
    gr:validFrom "2010-05-01T00:00:00Z"^^xsd:dateTime ;
    gr:validThrough "2010-12-31T23:59:59Z"^^xsd:dateTime ;
    gr:hasPriceSpecification foo:price1, foo:price2.

Case 2: The price per unit is reduced for ALL items beyond a certain minimum quantity

Example: Something costs 4 USD per kilogram for purchases of up to 5 kilogram 3 USD for any quantity beyond that. If you buy 9 kilogram, you will have to pay

  • 9 kg * 3 USD = 27 USD

GoodRelations pattern: You have to use two gr:Offering instances in this case, one for quantities up to 5 kg and one for quantites beyond 5 kg. So in this second scenario, you constrain the validity of the two offers using non-overlapping gr:hasEligibleQuantity and gr:hasUnitOfMeasurement properties. Since there is no way to indicate "greater than", we have to use "5.00000001"^^xsd:float in the example below.

# We sell potatoes for 4 USD per kg if you buy between 0 and 5 kg
foo:offer1 a gr:Offering ;
    rdfs:label "Potatoes for sale"@en ;
    rdfs:comment "We sell potatoes"@en ;
    gr:hasBusinessFunction gr:Sell ;
    gr:validFrom "2010-05-01T00:00:00Z"^^xsd:dateTime ;
    gr:validThrough "2010-12-31T23:59:59Z"^^xsd:dateTime ;
    gr:hasPriceSpecification foo:price1 ;
    gr:hasEligibleQuantity [ a gr:QuantitativeValue ;
                            gr:hasUnitOfMeasurement "KGM"^^xsd:string ;
                            gr:hasMinValue "0"^^xsd:float ;
                            gr:hasMaxValue "5"^^xsd:float ] .
foo:price1 a gr:UnitPriceSpecification  ;
    gr:hasCurrency "USD"^^xsd:string ;
    gr:hasCurrencyValue "4.0"^^xsd:float ;
    gr:hasUnitOfMeasurement "KGM"^^xsd:string ;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean .

# We sell potatoes for 3 USD per kg if you buy more than 5 kg
foo:offer2 a gr:Offering ;
    rdfs:label "Potatoes for sale"@en ;
    rdfs:comment "We sell potatoes"@en ;
    gr:hasBusinessFunction gr:Sell ;
    gr:validFrom "2010-05-01T00:00:00Z"^^xsd:dateTime ;
    gr:validThrough "2010-12-31T23:59:59Z"^^xsd:dateTime ;
    gr:hasPriceSpecification foo:price2 ;
    gr:hasEligibleQuantity [ a gr:QuantitativeValue ;
                            gr:hasUnitOfMeasurement "KGM"^^xsd:string ;
                            gr:hasMinValue "5.00000001"^^xsd:float ].

foo:price2 a gr:UnitPriceSpecification ;
    gr:hasCurrency "USD"^^xsd:string ;
    gr:hasCurrencyValue "3.0"^^xsd:float ;
    gr:hasUnitOfMeasurement "KGM"^^xsd:string ;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean .

Important: Don't forget to use gr:offers to link from the company (gr:BusinessEntity) to BOTH offers (gr:Offering) now:

foo:company gr:offers foo:offer1, foo:offer2 .

Seasonal Discounts and Special Offers

Simply attach multiple gr:UnitPriceSpecification instances to the gr:Offering and constrain their temporal validity using gr:validFrom and gr:validThrough.

Example: 4 USD per kilogram, 3 USD from May 1 - June 30, 2010

# 4 USD per kilogram from July 1 - December 31, 2010
foo:price1 a gr:UnitPriceSpecification ;
    gr:hasCurrency "USD"^^xsd:string ;
    gr:hasCurrencyValue "4.0"^^xsd:float ;
    gr:hasUnitOfMeasurement "KGM"^^xsd:string ;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean ;
    gr:validFrom "2010-07-01T00:00:00Z"^^xsd:dateTime ;
    gr:validThrough "2010-12-31T23:59:59Z"^^xsd:dateTime .

# 4 USD per kilogram from May 1 - June 30, 2010
foo:price2 a gr:UnitPriceSpecification ;
    gr:hasCurrency "USD"^^xsd:string ;
    gr:hasCurrencyValue "3.0"^^xsd:float ;
    gr:hasUnitOfMeasurement "KGM"^^xsd:string ;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean ;
    gr:validFrom "2010-05-01T00:00:00Z"^^xsd:dateTime ;
    gr:validThrough "2010-06-30T23:59:59Z"^^xsd:dateTime .


Same as in the previous example, you have to link from the offering to both price specifications now.

Change

  • gr:hasPriceSpecification foo:price.

to

  • gr:hasPriceSpecification foo:price1, foo:price2.


Billing Increments

The property gr:billingIncrement with a domain of gr:UnitPriceSpecification and a range of xsd:float allows indicating the smallest billable unit of an item.

Examples:

  • Price 2 euro per hour, billing in units of 15 minutes
  • The price be 4 USD per kilogram of potatoes, but the billing will be based on the quantity rounded up to the next multiple of 100 grams.

The UN/CEFACT Common Code for "kilogram" is "KGM", that for gram is "GRM". Note that you have to use the same unit for the billing increment and the unit of measurement for the price reference, so either you express this as 4 USD per kilogram with an increment of 0.1 kilograms or as a price of 0.004 USD per gram with a billing increment of 100 grams.

# 4 USD per kilogram, billing increment 100 g
foo:price a gr:UnitPriceSpecification;
    gr:hasCurrency "USD"^^xsd:string;
    gr:hasCurrencyValue "4.0"^^xsd:float;
    gr:hasUnitOfMeasurement "KGM"^^xsd:string;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean ;
    gr:billingIncrement "0.1"^^xsd:float .

Important: The billing increment specifies only the rounding steps for determining the billable quantity. The price is given per unit of measurement. For instance, the example above expresses that the price is 4 USD per kilogram and not 4 USD per 0.1 kilograms.

Price Ranges

Sometimes, the price can only be given as an interval, depending on characteristics of the actual item or the buying party. Simply use gr:hasMaxCurrencyValue and gr:hasMinCurrencyValue for the upper and lower bounds instead of gr:hasCurrencyValue. An RDFS-style reasoner will expand gr:hasCurrencyValue to two matching gr:hasMinCurrencyValue and gr:hasMaxCurrencyValue statements anyway. When querying, you should process gr:hasMinCurrencyValue and gr:hasMaxCurrencyValue instead of gr:hasCurrencyValue, unless you want to ignore offers that give ranges only.

# 3..4 USD per kilogram, depending on the size of the potatoes
foo:price a gr:UnitPriceSpecification ;
    gr:hasCurrency "USD"^^xsd:string ;
    gr:hasMinCurrencyValue "3.0"^^xsd:float ;
    gr:hasMaxCurrencyValue "4.0"^^xsd:float ;
    gr:hasUnitOfMeasurement "KGM"^^xsd:string ;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean .

Indicating List Prices

You can indicate retails prices as recommended by the supplier etc. using the gr:priceType property. This attribute can be used to distinguish multiple different gr:UnitPriceSpecification instances for the same offer. It supersedes the former gr: isListPrice property. The following values are recommended:

  • SRP: "suggested retail price" - applicable for all sorts of a non-binding retail price recommendations, e.g. such published by the manufacturer or the distributor. This value replaces the former gr:isListPrice property.
  • INVOICE: The invoice price, mostly used in the car industry - this is the price a dealer pays to the manufacturer, excluding rebates and charges.

The absence of this property marks the actual sales price.

# 4 USD per kilogram with a "suggested retail price" of 4.50 USD.

foo:price1 a gr:UnitPriceSpecification ;
    gr:hasCurrency "USD"^^xsd:string ;
    gr:hasCurrencyValue "4.0"^^xsd:float ;
    gr:hasUnitOfMeasurement "KGM"^^xsd:string ;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean .

foo:price2 a gr:UnitPriceSpecification ;
    gr:hasCurrency "USD"^^xsd:string ;
    gr:hasCurrencyValue "4.5"^^xsd:float ;
    gr:hasUnitOfMeasurement "KGM"^^xsd:string ;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean ;
    gr:priceType "SRP"^^xsd:string .

Car Rental: 25 USD / day plus 1 USD per mile

You can combine multiple gr:UnitPriceSpecification instances that are valid in combination. For example, a rental car business might say that the price for a particular rental car is 25 USD per day plus 1 USD per mile.

Note that the UN/CEFACT Common Code for "day" is "DAY", that for "car mile" is "1A". Also note that the gr:BusinessFunction for rental is gr:LeaseOut.

# Car Rental: 25 USD / day, 1 USD per mile

foo:company a gr:BusinessEntity ;
    gr:legalName "Hepp Space Ventures, Inc."@en ;
    gr:offers foo:car_offer.

foo:car_offer a gr:Offering ;
    rdfs:label "Car rental"@en ;
    rdfs:comment "We rent out cars"@en ;
    gr:hasBusinessFunction gr:LeaseOut ;
    gr:hasPriceSpecification foo:rental_price1, foo:rental_price2 .

foo:rental_price1 a gr:UnitPriceSpecification ;
    gr:hasCurrency "USD"^^xsd:string ;
    gr:hasCurrencyValue "25"^^xsd:float ;
    gr:hasUnitOfMeasurement "DAY"^^xsd:string ;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean .

foo:rental_price2 a gr:UnitPriceSpecification ;
    gr:hasCurrency "USD"^^xsd:string ;
    gr:hasCurrencyValue "1"^^xsd:float ;
    gr:hasUnitOfMeasurement "1A"^^xsd:string ;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean .

Note: The vehicles being offered can (and should) be described in more detail. See the other GoodRelations recipes for examples. This recipe focuses on modeling the pricing.

Cancellation Rules

GoodRelations does not provide a means for modeling cancellation policies and fees in detail, but you can easily attach them using

rdfs:comment

to the gr:UnitPriceSpecification node.

foo:rental_price a gr:UnitPriceSpecification ;
    gr:hasCurrency "USD"^^xsd:string ;
    gr:hasCurrencyValue "75"^^xsd:float ;
    gr:hasUnitOfMeasurement "DAY"^^xsd:string ;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean ;
    rdfs:comment "Cancellation Policy: You can cancel free of charge up to 72 hours
 prior to the start of the lease.
 In case of any later cancellation, we will charge the rental fees for one day."@en.

Complex Examples

Boat Rental: 100 USD / day 0-3 days, 75 USD per day for any longer rental

Turtle Syntax

# Boat Rental: 100 USD / day 0-3 days, 75 USD per day for any longer rental

foo:company a gr:BusinessEntity ;
    gr:legalName "Hepp Space Ventures, Inc."@en ;
    gr:offers foo:boat_offer.

foo:boat_offer a gr:Offering ;
    rdfs:label "Boat rental"@en ;
    rdfs:comment "We rent out boats"@en ;
    gr:hasBusinessFunction gr:LeaseOut ;
    gr:hasPriceSpecification foo:rental_price1, foo:rental_price2 .

foo:rental_price1 a gr:UnitPriceSpecification ;
    gr:hasCurrency "USD"^^xsd:string ;
    gr:hasCurrencyValue "100"^^xsd:float ;
    gr:hasUnitOfMeasurement "DAY"^^xsd:string ;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean ;
    gr:hasEligibleQuantity [ a gr:QuantitativeValueInteger ;
                            gr:hasUnitOfMeasurement "DAY"^^xsd:string ;
                            gr:hasMinValueInteger "0"^^xsd:int ;
                            gr:hasMaxValueInteger "3"^^xsd:int . ].

foo:rental_price2 a gr:UnitPriceSpecification ;
    gr:hasCurrency "USD"^^xsd:string ;
    gr:hasCurrencyValue "75"^^xsd:float ;
    gr:hasUnitOfMeasurement "DAY"^^xsd:string ;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean ;
    gr:hasEligibleQuantity [ a gr:QuantitativeValueInteger ;
                            gr:hasUnitOfMeasurement "DAY"^^xsd:string ;
                            gr:hasMinValueInteger "4"^^xsd:int . ].

RDFa Syntax

<div xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
       xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
       xmlns="http://www.w3.org/1999/xhtml"
       xmlns:gr="http://purl.org/goodrelations/v1#"
       xmlns:foo="http://www.example.com/xyz#"
       xmlns:xsd="http://www.w3.org/2001/XMLSchema#" >
  <div about="http://www.example.com/xyz#company" typeof="gr:BusinessEntity">
    <div property="gr:legalName" content="Hepp Space Ventures, Inc." xml:lang="en"></div>
    <div rel="gr:offers">
      <div about="http://www.example.com/xyz#boat_offer" typeof="gr:Offering">
        <div property="rdfs:comment" content="We rent out boats" xml:lang="en"></div>
        <div rel="gr:hasBusinessFunction"
               resource="http://purl.org/goodrelations/v1#LeaseOut"></div>
        <div rel="gr:hasPriceSpecification">
          <div about="http://www.example.com/xyz#rental_price2" typeof="gr:UnitPriceSpecification">
            <div property="gr:hasCurrency" content="USD" datatype="xsd:string"></div>
            <div property="gr:hasCurrencyValue" content="75" datatype="xsd:float"></div>
            <div rel="gr:hasEligibleQuantity">
              <div typeof="gr:QuantitativeValueInteger">
                <div property="gr:hasMinValueInteger" content="4" datatype="xsd:int"></div>
                <div property="gr:hasUnitOfMeasurement" content="DAY" datatype="xsd:string"></div>
              </div>
            </div>
            <div property="gr:hasUnitOfMeasurement" content="DAY" datatype="xsd:string"></div>
            <div property="gr:valueAddedTaxIncluded" content="true" datatype="xsd:boolean"></div>
          </div>
        </div>
        <div rel="gr:hasPriceSpecification">
          <div about="http://www.example.com/xyz#rental_price1" typeof="gr:UnitPriceSpecification">
            <div property="gr:hasCurrency" content="USD" datatype="xsd:string"></div>
            <div property="gr:hasCurrencyValue" content="100" datatype="xsd:float"></div>
            <div rel="gr:hasEligibleQuantity">
              <div typeof="gr:QuantitativeValueInteger">
                <div property="gr:hasMaxValueInteger" content="3" datatype="xsd:int"></div>
                <div property="gr:hasMinValueInteger" content="0" datatype="xsd:int"></div>
                <div property="gr:hasUnitOfMeasurement" content="DAY" datatype="xsd:string"></div>
              </div>
            </div>
            <div property="gr:hasUnitOfMeasurement" content="DAY" datatype="xsd:string"></div>
            <div property="gr:valueAddedTaxIncluded" content="true" datatype="xsd:boolean"></div>
          </div>
        </div>
        <div property="rdfs:label" content="Boat rental" xml:lang="en"></div>
      </div>
    </div>
  </div>
</div>

Boat Rental: 24 USD / 6 hours for 0-3 days, 75 USD per day for any longer rental

Note that the price information "24 USD per 6 hours" must be translated into 24/6 = 4 USD per hour and a billing increment of 6.0 hours. The UN/CEFACT Common Code for "hour" is "HUR".

# Boat Rental: 24 USD / 6 hours for 0-3 days, 75 USD per day for any longer rental

foo:rental_price1 a gr:UnitPriceSpecification ;
    gr:hasCurrency "USD"^^xsd:string ;
    # 24 USD per 6 hours => 4 USD / hour
    gr:hasCurrencyValue "4"^^xsd:float ;
    gr:hasUnitOfMeasurement "HUR"^^xsd:string ;
    gr:billingIncrement "6"^^xsd:float
    gr:valueAddedTaxIncluded "true"^^xsd:boolean ;
    gr:hasEligibleQuantity
        [ a gr:QuantitativeValueInteger ;
          gr:hasUnitOfMeasurement "DAY"^^xsd:string ;
          gr:hasMinValueInteger "0"^^xsd:int ;
          gr:hasMaxValueInteger "3"^^xsd:int . ].

foo:rental_price2 a gr:UnitPriceSpecification ;
    gr:hasCurrency "USD"^^xsd:string ;
    gr:hasCurrencyValue "75"^^xsd:float ;
    gr:hasUnitOfMeasurement "DAY"^^xsd:string ;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean ;
    gr:hasEligibleQuantity
        [ a gr:QuantitativeValueInteger ;
          gr:hasUnitOfMeasurement "DAY"^^xsd:string ;
          gr:hasMinValueInteger "4"^^xsd:int . ].