I offered to post the script I use to track freebie items, and here it is:
Put this script into a prim containing the freebie items to give copies of
Name the prim with same name you want to use for the folder in the freebie-e's inventory
- When touched, offers toucher a folder (with the same name as the prim) containing a copy of the box content
- Records who has touched it, and how many times each person has touched it
- At a <specified> interval, it sends an email to a <specified> email address, with the records for that period.
Further details are in the script header.
And I'd be happy to have feedback or suggestions for improvement.

Cheers, Fairge
CODE
// Fairge Kinsella, Peterg Codesmith - Gravity Works
// Adapted from a script Jeffrey Gomez posted on the forums
// http://forums.secondlife.com/showthread.php?t=45170&highlight=folder
// Summary
// When touched, offers toucher a folder containing a copy of the box content
// Records who has touched it, and how many times each person has touched it
// At a <specified> interval, it sends an email to a <specified> email address, with the records for that period.
// Detailed description
// When touched, gets a list of the content, and offers it to the toucher
// Content is offered in a folder with the same name as the object
// If there is no content to give, it whispers that the box is empty, and to contact the owner
// (The touch is not recorded in this case)
// Holds a history list of people who have touched, in the format <Name> <No. Times Touched>
// When someone touches, it checks to see if they are already in the list. If not, it adds them, and records they've
// touched once.
// If the toucher is already in the list, it adds 1 to <No. Times Touched>
// When a timer set to <iReportFrequency> fires, it assembles the history list into a string
// If there are entries in the list, sends an email to <strReportEmail> containing the string
// Corrections
// It would be better to call prepareFolder() from the initialise() function, instead every time there's a touch.
// I've just left it in the touch event because I'm changing the object name and contents heaps during testing
// There seems to be some oddness when using "/n" in an email, some people (including me) do not see a newline
// ********************************************************************************
// Globals start here
// ********************************************************************************
// Owner specific details
string strReportEmail = "your.email@somewhere.com"; // SET TO YOUR EMAIL ADDRESS
integer iReportFrequency = 86400; // SET TO HOW OFTEN YOU WANT TO GET A REPORT
// One week = 604800 seconds
// One day = 86400 seconds
// Freebie info
string strFolderName;
list lstContents;
// Reporting information
list lstHistory;
integer HISTORY_REC_LEN = 2;
// ********************************************************************************
// Methods start here
// ********************************************************************************
initialise()
{
llOwnerSay(llGetScriptName() + " is starting to initialise");
llSetTimerEvent( iReportFrequency );
llOwnerSay(llGetScriptName() + " is finished initialising");
}
prepareFolder() // get the folder name, and list of content to give in the folder
{
strFolderName = llGetObjectName(); // Give in a folder named as this object
lstContents = [];
string strItemName = "";
integer iNoItems = llGetInventoryNumber(INVENTORY_ALL);
integer x;
for (x = 0; x < iNoItems; x++) // create the list of items to give
{
strItemName = llGetInventoryName(INVENTORY_ALL, x); // get the name of every item in the box
if (strItemName != llGetScriptName()) lstContents += [strItemName]; // Skip this script
}
}
updateHistoryList(string strToucherName) // Runs each time someone touches, and adds the toucher to the list
{
list lstName = [strToucherName];
// Search to see if the toucher's name is already in the list
integer iListPos = llListFindList(lstHistory, lstName);
if (iListPos == -1) // Avatar is not in list, add them, with a touch count of 0
{
list lstNewEntry = [strToucherName, 0];
iListPos = 0;
lstHistory = llListInsertList(lstHistory, lstNewEntry, iListPos);
}
// get the number of times the Av has touched, and add 1
integer iNewFreebieCount = llList2Integer(lstHistory, iListPos + 1);
iNewFreebieCount = iNewFreebieCount + 1;
// replace the entry for the toucher in the list with the new details
list lstNewEntry = [strToucherName, iNewFreebieCount];
lstHistory = llListInsertList(llDeleteSubList(lstHistory, iListPos, iListPos+ HISTORY_REC_LEN - 1), lstNewEntry, iListPos);
}
string printHistoryList() // Compiles a string for the history list
{
integer pos;
integer iLength = llGetListLength(lstHistory);
string strResult;
if ( iLength == 0 ) // There are no entires in the history list
{
strResult = "Nothing to report.";
}
else
{
// puts list entries into a single string in the format
// <Name1>, <No. Times Touched1>; <NameX>, <No. Times TouchedX>;
for(pos = 0; pos < iLength; pos += HISTORY_REC_LEN)
{
string strHistoryAvatarName = llList2String(lstHistory, pos);
string strFreebieCount = llList2String(lstHistory, pos + 1);
strResult = strResult + strHistoryAvatarName + ", " + strFreebieCount + ";\n ";
}
}
return strResult;
}
// ********************************************************************************
// States start here
// ********************************************************************************
default
{
state_entry()
{
initialise();
state running;
}
on_rez(integer start_param)
{
initialise();
state running;
}
}
state running
{
touch_start(integer iTotalTouches)
{
while (iTotalTouches)
{
iTotalTouches--; //count backwards from last item in array
key kWho = llDetectedKey(iTotalTouches); // key of avatar that touched
string strToucherName = llKey2Name(kWho);
prepareFolder();
if (llGetListLength(lstContents) == 0) // there is no content to give
{
llWhisper(0, "This box is empty, please contact the owner");
}
else
{
llGiveInventoryList(kWho, strFolderName, lstContents); // give the content in a folder
updateHistoryList(strToucherName);
}
}
}
timer()
{
state reporting;
}
}
state reporting
{
state_entry()
{
string strHistoryReport = printHistoryList();
if ( llSubStringIndex(strHistoryReport, "Nothing to report.") != 0) // If the list wasn't empty
{
string strGameName = llGetObjectName();
strHistoryReport = strGameName + " report: " + strHistoryReport;
llEmail(strReportEmail, "Freebie Report", strHistoryReport);
lstHistory = [];
}
state running;
}
state_exit()
{
llSetTimerEvent( iReportFrequency ); //reset report timer
}
}