This section describes extensions made to ATG Consumer Commerce and DPS for the Pioneer Cycling store site. DPS performs the collection, storage, and retrieval of data specific to individual users of the Web application. A profile is the data stored for an individual customer based on forms she fills out or her actions on the site. Once this data is collected, it provides Web site developers the ability to show the customer personalized products and content based on this profile.
In the Pioneer Cycling site, we used personalization in a variety of ways to make a compelling shopping experience. DPS provides basic personalization capability, but you can easily extend this functionality to fit the needs of your Web application. The Pioneer Cycling site demonstrates several ways to extend this functionality. Please refer to the Setting up a Profile Repository chapter in the ATG Personalization Programming Guide and the SQL Content Repositories chapter in the ATG Repository Guide for more detailed information about the SQL Repository definitions in DPS and Consumer Commerce.
DPS stores customer data in a repository, which consists of user
item types and several supporting item types. The default DPS repository contains item types defined with the set of properties that are needed by most personalized Web applications. In ATG Consumer Commerce, some additional properties have been added to the user
item type to make possible many commerce features. Pioneer Cycling adds yet more item types and properties to provide functionality that is specific to a bike store.
These extensions are defined in the XML file <ATG2007.3dir>/atg/userprofiling/userProfile.xml
. This file is combined with the files of the same name from ATG Consumer Commerce, DSS, and DPS. These files are combined per the rules of XML combination to produce one XML file that is then parsed and used by ATG to describe the item types in the repository. (See the Nucleus: Organizing JavaBean Components chapter of the for more information on XML file combination.) The combined file is reparsed each time the repository starts and it is never written out to disk, so we only need to maintain the separate files, not the combined one.
The underlying storage of the user profile repository in Pioneer Cycling is a relational database. The SQL Profile Repository is used to expose that data via the Repository API. In the XML file, we describe the mapping of repository items to the relational database tables and columns.
Here are the properties we added to the user
item type:
Property | Description |
---|---|
| The customer’s clothing size. We use this property for targeting size-appropriate clothing to the user. |
| This integer value is incremented or decremented according to the weight class of the items purchased by the customer. If the customer purchases many lightweight items, he has a low value for |
| This property works much like |
| A count of the number of orders that this user has placed with the store. This can be used as a measure of customer loyalty. |
| A running total of the amount of money spent on the site. This can be used for targeting promotions or identifying trends in the customer base. This number represents the amount spent in the currency indicated by the customer’s selected locale. If the user changes his locale from |
| We use a scenario to keep track of the types of bikes a user owns so that we can target compatible products to the user. |
| A list of keywords the customer picks up based on his activities in the store. This property’s value is populated by DSS. When a user purchases a product, that product’s keywords are appended to the |
| A list of the IDs of items purchased by the user. |
| This transient property keeps track of a list of the catalog categories recently visited by the user. |
| This transient property keeps track of a list of the products recently visited by the user. |
| This transient property keeps track of a list of the strings that the user has searched on recently. |
The following example shows the XML file for Pioneer Cycling. Please refer to the SQL Repository Architecture chapter in the ATG Repository Guide for the proper definition file syntax.
<gsa-template xml-combine="append"> <header> <name>Bikestore Related Profile Changes</name> <author>DCS Team</author> <version>$Change: 224215 $$DateTime: 2001/12/27 14:00:56 $$Author: bbarber $</version> </header> <item-descriptor name="user"> <table name="b2c_user" type="auxiliary" id-column-name="id"> <attribute name="resourceBundle" value="atg.projects.b2cstore.UserProfileTemplateResources"/> <property category-resource="categoryPioneerCycling" name="size" data-type="enumerated" default="clothingSizeUnknown" column-name="clothing_size" display-name-resource="clothingSize"> <attribute name="resourceBundle" value="atg.projects.b2cstore.UserProfileTemplateResources"/> <attribute name="useCodeForValue" value="false"/> <option resource="clothingSizeUnknown" code="0"/> <option resource="clothingSizeExtraSmall" code="1"/> <option resource="clothingSizeSmall" code="2"/> <option resource="clothingSizeMedium" code="3"/> <option resource="clothingSizeLarge" code="4"/> <option resource="clothingSizeExtraLarge" code="5"/> </property> <property category-resource="categoryPioneerCycling" name="weightPreference" data-type="int" column-name="weight_preference" display-name-resource="weightPreference"> <attribute name="resourceBundle" value="atg.projects.b2cstore.UserProfileTemplateResources"/> </property> <property category-resource="categoryPioneerCycling" name="pricePreference" data-type="int" column-name="price_preference" display-name-resource="pricePreference"> <attribute name="resourceBundle" value="atg.projects.b2cstore.UserProfileTemplateResources"/> </property> <property category-resource="categoryPioneerCycling" name="numOrders" display-name-resource="numOrders" data-type="int" column-name="num_orders" default="0"> <attribute name="resourceBundle" value="atg.projects.b2cstore.UserProfileTemplateResources"/> </property> <property category-resource="categoryPioneerCycling" name="cumulativeOrderAmount" display-name-resource="cumulativeOrderAmount" data-type="double" column-name="cum_order_amt" default="0"> <attribute name="resourceBundle" value="atg.projects.b2cstore.UserProfileTemplateResources"/> </property> </table> <table name="b2c_bike_owned" type="multi" id-column-name="id" multi-column-name="sequence_num"> <property category-resource="categoryPioneerCycling" name="bikesYouOwn" data-type="list" component-data-type="String" column-name="bike" display-name-resource="bikesYouOwn"> <attribute name="resourceBundle" value="atg.projects.b2cstore.UserProfileTemplateResources"/> </property> </table> <table name="b2c_user_keyword" type="multi" id-column-name="id" multi-column-name="sequence_num"> <property category-resource="categoryPioneerCycling" name="userKeywords" data-type="list" component-data-type="String" column-name="keyword" display-name-resource="userKeywords"> <attribute name="resourceBundle" value="atg.projects.b2cstore.UserProfileTemplateResources"/> </property> </table> <table name="b2c_item_bought" type="multi" id-column-name="id" multi-column-name="sequence_num"> <attribute name="resourceBundle" value="atg.projects.b2cstore.UserProfileTemplateResources"/> <property category-resource="categoryPioneerCycling" name="itemsBought" data-type="list" component-item-type="sku" repository="/atg/commerce/catalog/ProductCatalog" column-name="item" display-name-resource="itemsBought"> <attribute name="resourceBundle" value="atg.projects.b2cstore.UserProfileTemplateResources"/> </property> </table> <!-- The following transient properties used to record categories & pages viewed, and recent searches --> <property category-resource="categoryPioneerCycling" name="categoriesViewed" display-name-resource="categoriesViewed" data-type="set" component-data-type="String"> <attribute name="resourceBundle" value="atg.projects.b2cstore.UserProfileTemplateResources"/> </property> <property category-resource="categoryPioneerCycling" name="productsViewed" display-name-resource="productsViewed" data-type="set" component-data-type="String"> <attribute name="resourceBundle" value="atg.projects.b2cstore.UserProfileTemplateResources"/> </property> <property category-resource="categoryPioneerCycling" name="recentSearches" display-name-resource="recentSearches" data-type="set" component-data-type="String"> <attribute name="resourceBundle" value="atg.projects.b2cstore.UserProfileTemplateResources"/> </property> </item-descriptor> </gsa-template>
We used the following SQL script to create the database schema to store the user profile data. Note that the tables declared in the XML as type="auxiliary"
have one row per user. The tables declared as type="multi"
have one row per user per value, so if there are1000 users and each customer purchases 5 items, there will be 5000 rows in the b2c_item_bought
table.
CREATE TABLE b2c_user ( id VARCHAR(40) NOT NULL, clothing_size INT NULL, wants_prod_reviews TINYINT NULL, weight_preference INTEGER NULL, price_preference INTEGER NULL, num_orders INTEGER NULL, cum_order_amt DOUBLE PRECISION NULL, PRIMARY KEY(id) ); CREATE TABLE b2c_user_keyword ( id VARCHAR(40) NOT NULL, sequence_num INTEGER NOT NULL, keyword VARCHAR(50) NOT NULL, PRIMARY KEY(id, sequence_num) ); CREATE TABLE b2c_item_bought ( id VARCHAR(40) NOT NULL, sequence_num INTEGER NOT NULL, item VARCHAR(40) NOT NULL, PRIMARY KEY(id, sequence_num) ); CREATE TABLE b2c_bike_owned ( id VARCHAR(40) NOT NULL, sequence_num INTEGER NOT NULL, bike VARCHAR(40) NOT NULL, PRIMARY KEY(id, sequence_num) );