Home » Academic Works » How To | Dynamic feedback links in Digital Commons documents


Problem? Check out the OLS Knowledge Base or open a ticket by emailing support@cuny-ols.libanswers.com.

How To | Dynamic feedback links in Digital Commons documents

At the beginning of this year, we announced a new feature in our institutional repository: a feedback form. It’s used to gather input from users of the repository to understand how access to these works benefits them:

Screenshot of a Digital Commons title page, with a feedback link in the footer circled in red

If you’re running a repository using bepress’s Digital Commons and want to implement this feature, read on!

You will need the assistance of your consultant at Digital Commons to create the dynamic link in the footer of the PDF cover pages. Otherwise, most of the work needed to accomplish this in your repository can be handled by you—and/or a colleague with access to your institution’s web server. It’s a single HTML page with a form (handled by Google) and some JavaScript, all of which are provided in this tutorial.

  1. Create a Google Form with 7 fields:
    1. referrer [text]
    2. benefit [paragraph text]
    3. name [text]
    4. email [text]
    5. country [text]
    6. role [multiple choice with ‘other’]
    7. permission [multiple choice

    (Don’t spend too much time picking a template: no one will see this form since we’ll be embedding it into an external HTML page.)

  2. Create a new spreadsheet that will save the responses (by clicking on the “Choose response destination” button in the toolbar) and click on the “View live form” button.
  3. Right-click and view the source code of the form. Find the following items:
    • <form> tag
      note the URL that is its “action” parameter (in the form of https://docs.google.com/forms/d/[FORM_ID]/formResponse, where [FORM_ID] is a long string of characters)
    • <input> elements
      note the name of each (in the form of entry.[xxxxxx], where [xxxxxx] is a string of numeric characters)
  4. On your institution’s server, create a new HTML page and insert the following into the file (replacing [FORM_ID] and entry.[xxxxxx] with the names from your form, and customizing the look & feel for your repository):
<!DOCTYPE html>
<html lang="en" />
	<meta charset="utf-8" />
	<meta http-equiv="X-UA-Compatible" content="IE=edge" />
	<meta name="viewport" content="width=device-width, initial-scale=1" />
	<title>CUNY Academic Works | How does access to this work benefit you?</title>
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous" />
	<link rel="stylesheet" href="http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" crossorigin="anonymous" />

<div class="container">
	<div class="jumbotron">
		<div class="row">
			<div class="col-sm-3">
				<img src="CUNY_Academic_Works_LOGO.png" style="max-width:100%;" />
			<div class="col-sm-9">
				<p class="lead" style="margin-top:20px;">Please let us know how open access to CUNY Academic Works has benefited you.</p>
	<div class="row marketing">
		<script type="text/javascript">var submitted=false;</script>
		// REPLACE 'thanks.html' (below) WITH YOUR OWN THANKS PAGE (if different)!
		<iframe name="hidden_iframe" id="hidden_iframe" style="display:none;" onload="if(submitted) {window.location='thanks.html';}"></iframe>
		<form class="form-horizontal" action="https://docs.google.com/forms/d/[FORM_ID]/formResponse" method="POST" id="feedback_form" target="hidden_iframe" onsubmit="submitted=true;">
			<fieldset class="form-group">
				<label for="entry.[referrer]" class="col-sm-4 control-label">
					Which work did you access?<br />
					<small class="muted">Please include the link or the title.</small>
				<div class="col-sm-8">
					<input type="text" class="form-control" placeholder="" id="entry.[referrer]" name="entry.[referrer]" required="required" />
				function gup( name, url ) {
					if (!url) url = location.href
					name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
					var regexS = "[\\?&]"+name+"=([^&#]*)";
					var regex = new RegExp( regexS );
					var results = regex.exec( url );
					return results == null ? null : results[1];
				var article = gup( 'article', window.location.href );
				var context = gup( 'context', window.location.href );
				var ref = gup( 'ref', window.location.href );
				if( article && context ) {
					// if article & context are provided by the referring URL, recreate the URL & populate [referrer] field with it
					document.forms["feedback_form"]["entry.[referrer]"].value = "http://academicworks.cuny.edu/cgi/viewcontent.cgi?article=" + article + "&context=" + context;
				} else if( ref ) {
					// if referring URL is provided by the referring URL, grab it in its entirety and populate [referrer] field with it
					document.forms["feedback_form"]["entry.[referrer]"].value = ref;
				} else if( document.referrer ) {
					// if no ref or article+context provided by referring URL, use the browser's referring URL (if one exists) to populate the [referrer] field
					document.forms["feedback_form"]["entry.[referrer]"].value = document.referrer;
			<fieldset class="form-group">
				<label for="entry.[benefit]" class="col-sm-4 control-label">How does access to this work benefit you?</label>
				<div class="col-sm-8">
					<textarea class="form-control" id="entry.[benefit]" name="entry.[benefit]" required="required"></textarea>
			<fieldset class="form-group">
				<label for="entry.[name]" class="col-sm-4 control-label">Name (optional)</label>
				<div class="col-sm-8">
					<input type="text" class="form-control" placeholder="" id="entry.[name]" name="entry.[name]" />
			<fieldset class="form-group">
				<label for="entry.[email]" class="col-sm-4 control-label">Email (optional)</label>
				<div class="col-sm-8">
					<input type="text" class="form-control" placeholder="" id="entry.[email]" name="entry.[email]" />
			<fieldset class="form-group">
				<label for="entry.[country]" class="col-sm-4 control-label">Country</label>
				<div class="col-sm-8">
					<select class="form-control" id="entry.[country]" name="entry.[country]" required="required">
						<option value=""></option>
						<option value="Afghanistan">Afghanistan</option>
						<option value="Albania">Albania</option>
						<option value="Algeria">Algeria</option>
						<option value="Andorra">Andorra</option>
						<option value="Angola">Angola</option>
						<option value="Antigua and Barbuda">Antigua and Barbuda</option>
						<option value="Argentina">Argentina</option>
						<option value="Armenia">Armenia</option>
						<option value="Australia">Australia</option>
						<option value="Austria">Austria</option>
						<option value="Azerbaijan">Azerbaijan</option>
						<option value="Bahamas">Bahamas</option>
						<option value="Bahrain">Bahrain</option>
						<option value="Bangladesh">Bangladesh</option>
						<option value="Barbados">Barbados</option>
						<option value="Belarus">Belarus</option>
						<option value="Belgium">Belgium</option>
						<option value="Belize">Belize</option>
						<option value="Benin">Benin</option>
						<option value="Bhutan">Bhutan</option>
						<option value="Bolivia">Bolivia</option>
						<option value="Bosnia and Herzegovina">Bosnia and Herzegovina</option>
						<option value="Botswana">Botswana</option>
						<option value="Brazil">Brazil</option>
						<option value="Brunei">Brunei</option>
						<option value="Bulgaria">Bulgaria</option>
						<option value="Burkina Faso">Burkina Faso</option>
						<option value="Burundi">Burundi</option>
						<option value="Cabo Verde">Cabo Verde</option>
						<option value="Cambodia">Cambodia</option>
						<option value="Cameroon">Cameroon</option>
						<option value="Canada">Canada</option>
						<option value="Central African Republic">Central African Republic</option>
						<option value="Chad">Chad</option>
						<option value="Chile">Chile</option>
						<option value="China">China</option>
						<option value="Colombia">Colombia</option>
						<option value="Comoros">Comoros</option>
						<option value="Congo, Republic of the">Congo, Republic of the</option>
						<option value="Congo, Democratic Republic of the">Congo, Democratic Republic of the</option>
						<option value="Costa Rica">Costa Rica</option>
						<option value="Cote d'Ivoire">Cote d'Ivoire</option>
						<option value="Croatia">Croatia</option>
						<option value="Cuba">Cuba</option>
						<option value="Cyprus">Cyprus</option>
						<option value="Czech Republic">Czech Republic</option>
						<option value="Denmark">Denmark</option>
						<option value="Djibouti">Djibouti</option>
						<option value="Dominica">Dominica</option>
						<option value="Dominican Republic">Dominican Republic</option>
						<option value="Ecuador">Ecuador</option>
						<option value="Egypt">Egypt</option>
						<option value="El Salvador">El Salvador</option>
						<option value="Equatorial Guinea">Equatorial Guinea</option>
						<option value="Eritrea">Eritrea</option>
						<option value="Estonia">Estonia</option>
						<option value="Ethiopia">Ethiopia</option>
						<option value="Fiji">Fiji</option>
						<option value="Finland">Finland</option>
						<option value="France">France</option>
						<option value="Gabon">Gabon</option>
						<option value="Gambia">Gambia</option>
						<option value="Georgia">Georgia</option>
						<option value="Germany">Germany</option>
						<option value="Ghana">Ghana</option>
						<option value="Greece">Greece</option>
						<option value="Grenada">Grenada</option>
						<option value="Guatemala">Guatemala</option>
						<option value="Guinea">Guinea</option>
						<option value="Guinea-Bissau">Guinea-Bissau</option>
						<option value="Guyana">Guyana</option>
						<option value="Haiti">Haiti</option>
						<option value="Honduras">Honduras</option>
						<option value="Hungary">Hungary</option>
						<option value="Iceland">Iceland</option>
						<option value="India">India</option>
						<option value="Indonesia">Indonesia</option>
						<option value="Iran">Iran</option>
						<option value="Iraq">Iraq</option>
						<option value="Ireland">Ireland</option>
						<option value="Israel">Israel</option>
						<option value="Italy">Italy</option>
						<option value="Jamaica">Jamaica</option>
						<option value="Japan">Japan</option>
						<option value="Jordan">Jordan</option>
						<option value="Kazakhstan">Kazakhstan</option>
						<option value="Kenya">Kenya</option>
						<option value="Kiribati">Kiribati</option>
						<option value="Kosovo">Kosovo</option>
						<option value="Kuwait">Kuwait</option>
						<option value="Kyrgyzstan">Kyrgyzstan</option>
						<option value="Laos">Laos</option>
						<option value="Latvia">Latvia</option>
						<option value="Lebanon">Lebanon</option>
						<option value="Lesotho">Lesotho</option>
						<option value="Liberia">Liberia</option>
						<option value="Libya">Libya</option>
						<option value="Liechtenstein">Liechtenstein</option>
						<option value="Lithuania">Lithuania</option>
						<option value="Luxembourg">Luxembourg</option>
						<option value="Macedonia">Macedonia</option>
						<option value="Madagascar">Madagascar</option>
						<option value="Malawi">Malawi</option>
						<option value="Malaysia">Malaysia</option>
						<option value="Maldives">Maldives</option>
						<option value="Mali">Mali</option>
						<option value="Malta">Malta</option>
						<option value="Marshall Islands">Marshall Islands</option>
						<option value="Mauritania">Mauritania</option>
						<option value="Mauritius">Mauritius</option>
						<option value="Mexico">Mexico</option>
						<option value="Micronesia">Micronesia</option>
						<option value="Moldova">Moldova</option>
						<option value="Monaco">Monaco</option>
						<option value="Mongolia">Mongolia</option>
						<option value="Montenegro">Montenegro</option>
						<option value="Morocco">Morocco</option>
						<option value="Mozambique">Mozambique</option>
						<option value="Myanmar (Burma)">Myanmar (Burma)</option>
						<option value="Namibia">Namibia</option>
						<option value="Nauru">Nauru</option>
						<option value="Nepal">Nepal</option>
						<option value="Netherlands">Netherlands</option>
						<option value="New Zealand">New Zealand</option>
						<option value="Nicaragua">Nicaragua</option>
						<option value="Niger">Niger</option>
						<option value="Nigeria">Nigeria</option>
						<option value="North Korea">North Korea</option>
						<option value="Norway">Norway</option>
						<option value="Oman">Oman</option>
						<option value="Pakistan">Pakistan</option>
						<option value="Palau">Palau</option>
						<option value="Palestine">Palestine</option>
						<option value="Panama">Panama</option>
						<option value="Papua New Guinea">Papua New Guinea</option>
						<option value="Paraguay">Paraguay</option>
						<option value="Peru">Peru</option>
						<option value="Philippines">Philippines</option>
						<option value="Poland">Poland</option>
						<option value="Portugal">Portugal</option>
						<option value="Qatar">Qatar</option>
						<option value="Romania">Romania</option>
						<option value="Russia">Russia</option>
						<option value="Rwanda">Rwanda</option>
						<option value="St. Kitts and Nevis ">St. Kitts and Nevis </option>
						<option value="St. Lucia">St. Lucia</option>
						<option value="St. Vincent and The Grenadines ">St. Vincent and The Grenadines </option>
						<option value="Samoa">Samoa</option>
						<option value="San Marino">San Marino</option>
						<option value="Sao Tome and Principe ">Sao Tome and Principe </option>
						<option value="Saudi Arabia">Saudi Arabia</option>
						<option value="Senegal">Senegal</option>
						<option value="Serbia">Serbia</option>
						<option value="Seychelles">Seychelles</option>
						<option value="Sierra Leone">Sierra Leone</option>
						<option value="Singapore">Singapore</option>
						<option value="Slovakia">Slovakia</option>
						<option value="Slovenia">Slovenia</option>
						<option value="Solomon Islands">Solomon Islands</option>
						<option value="Somalia">Somalia</option>
						<option value="South Africa">South Africa</option>
						<option value="South Korea">South Korea</option>
						<option value="South Sudan">South Sudan</option>
						<option value="Spain">Spain</option>
						<option value="Sri Lanka">Sri Lanka</option>
						<option value="Sudan">Sudan</option>
						<option value="Suriname">Suriname</option>
						<option value="Swaziland">Swaziland</option>
						<option value="Sweden">Sweden</option>
						<option value="Switzerland">Switzerland</option>
						<option value="Syria">Syria</option>
						<option value="Taiwan">Taiwan</option>
						<option value="Tajikistan">Tajikistan</option>
						<option value="Tanzania">Tanzania</option>
						<option value="Thailand">Thailand</option>
						<option value="Timor-Leste">Timor-Leste</option>
						<option value="Togo">Togo</option>
						<option value="Tonga">Tonga</option>
						<option value="Trinidad and Tobago">Trinidad and Tobago</option>
						<option value="Tunisia">Tunisia</option>
						<option value="Turkey">Turkey</option>
						<option value="Turkmenistan">Turkmenistan</option>
						<option value="Tuvalu">Tuvalu</option>
						<option value="Uganda">Uganda</option>
						<option value="Ukraine">Ukraine</option>
						<option value="United Arab Emirates">United Arab Emirates</option>
						<option value="United Kingdom">United Kingdom</option>
						<option value="United States of America">United States of America</option>
						<option value="Uruguay">Uruguay</option>
						<option value="Uzbekistan">Uzbekistan</option>
						<option value="Vanuatu">Vanuatu</option>
						<option value="Vatican City (Holy See)">Vatican City (Holy See)</option>
						<option value="Venezuela">Venezuela</option>
						<option value="Vietnam">Vietnam</option>
						<option value="Yemen">Yemen</option>
						<option value="Zambia">Zambia</option>
						<option value="Zimbabwe">Zimbabwe</option>
			<fieldset class="form-group">
				<label for="entry.[role]" class="col-sm-4 control-label">Which role best describes you?</label>
				<div class="col-sm-8">
						<label class="checkbox-inline">
							<input type="radio" id="entry.[role]_1" name="entry.[role]" value="Faculty" required="required" />
						<label class="checkbox-inline">
							<input type="radio" id="entry.[role]_2" name="entry.[role]" value="Researcher" required="required" />
						<label class="checkbox-inline">
							<input type="radio" id="entry.[role]_3" name="entry.[role]" value="Student" required="required" />
						<label class="checkbox-inline">
							<input type="radio" id="entry.[role]_4" name="entry.[role]" value="__other_option__" required="required" />
							<input type="text" class="form-control" placeholder="" id="entry.[role].other_option_response" name="entry.[role].other_option_response" />
			<fieldset class="form-group">
				<label for="entry.[permission]" class="col-sm-4 control-label">
					Can we share your comments?<br />
					<small class="muted">Your comments demonstrate the benefits of public scholarship, and we'd like to share them with others. All identifying information will remain anonymous.</small>
				<div class="col-sm-8">
						<label class="checkbox-inline">
							<input type="radio" id="entry.[permission]_1" name="entry.[permission]" value="Yes, I give CUNY permission to share my comments." required="required" />
							Yes, I give CUNY permission to share my comments.
						<label class="checkbox-inline">
							<input type="radio" id="entry.[permission]_2" name="entry.[permission]" value="No, CUNY does not have permission to share my comments." required="required" />
							No, CUNY does not have permission to share my comments.
			<fieldset class="form-group">
				<div class="form-group">
					<div class="col-sm-12">
						<button type="submit" class="btn btn-primary btn-lg btn-block">Submit</button>

	<footer class="footer">
		<p><a href="http://academicworks.cuny.edu/" target="_blank">CUNY Academic Works</a> is a service of CUNY Libraries, coordinated by the <a href="http://www2.cuny.edu/about/administration/offices/library-services/" target="_blank">Office of Library Services</a> of the <a href="http://www.cuny.edu/" target="_blank">City University of New York</a>.</p>

</div> <!-- /container -->

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
	<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
	<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>


Note the <script> and <iframe> tags in the code. What are they?

  • Lines 28-30
    • Upon hitting the “Submit” button in a Google Form, users are taken to a Google confirmation page. We want the user to stay on our site so we have to force this behavior on the server.
    • To do this, we create a Boolean variable (var submitted=false;, line 28) whose value changes upon the form submit (<form [...] onsubmit="submitted=true;">, line 31) and triggers a script that changes the window’s location (<iframe [...] onload="if(submitted) {window.location='thanks.html';_">, line 30) to a page that you will have created and populated with a nice message, thanking the user for taking the time out to explain how access to this work benefits them.
  • Lines 41-64
    • We fill one of the <input> elements with data we grab from the browser. This script can accommodate two different sets of parameters sent to the URL (“article” and “context” pair identifying the particular document [lines 53-57] or “ref,” which refers to the full URL of the document [lines 57-60]), as well as the referring URL (lines 60-63).

Et voilà! You now have a form that’s ready to accept submissions from users accessing your IR documents, storing them in a spreadsheet in your Google Drive account:

Screenshot of a Google Spreadsheet showing submissions using the feedback form linked from the PDF cover pages of documents in Digital Commons

By default, you do not get email notifications when a form is submitted. You can turn on this functionality in the Google Spreadsheet but all it will do is inform you when a user has submitted the form, without actually providing you with the form data in the email.

To overcome this, we’ll create a script that will send the results to you by email as soon as a user submits the form. In the response spreadsheet, go to Tools > Script editor > Blank Project and paste the following code into the editor (replacing placeholder variable values with your own):

function sendFormByEmail(e) {
	var emailSubject = "CAW | Feedback form";  
	// Set with your email address or a comma-separated list of email addresses.
	var yourEmail = "[recipient]";
	// Set with your spreadsheet's key, found in the URL when viewing your spreadsheet.
	var docKey = "[FORM_ID]";
	// If you want the script to auto send to all of the spreadsheet's editors, set this value as 1.
	// Otherwise set to 0 and it will send to the yourEmail values.
	var useEditors = 0;

	if (useEditors) {
		var editors = DocsList.getFileById(docKey).getEditors();
		if (editors) { 
			var sendTo = editors.join(',');
		} else var sendTo = yourEmail;
	} else {
		var sendTo = yourEmail;

	// The variable e holds all the submission values in an array.
	// Loop through the array and append values to the body.
	var s = SpreadsheetApp.getActive().getSheetByName("Form Responses 1");
	var headers = s.getRange(1,1,1,s.getLastColumn()).getValues()[0];
	var message = "";
	for(var i in headers) {
		message += headers[i] + ':\n\n'+ e.namedValues[headers[i]].toString() + '\n\n--\n\n'; 

	MailApp.sendEmail(sendTo, emailSubject, message);  

Click File > Save and give the project a name (such as ir_feedback). Go to Resources > Current project's triggers. Click “No triggers set up. Click here to add one now.” to add a trigger. Ensure the following values are selected in the drop-down menus: sendFormByEmail, From spreadsheet, On form submit. Click “Save.”

A message will be shown to authorize the script; click “Continue.” Read the terms and click “Accept.” It will approve the authorization for the trigger and bring you back to the code editor. You can now close the editor and go back to your spreadsheet because you’re all set!


You should now have a form, embedded in an HTML file on your institution’s server, that users can fill out to let you know how access to the work in your repository has impacted them. The results are stored in a spreadsheet in Google Drive and also emailed to the recipients listed in the script.

The next step is to contact your Digital Commons consultant and let him/her know that you want to link to this form from the footer in the auto-generated PDF cover pages of your collections:

Hi, [consultant]!

My institution would like to embed a link to a feedback form in the footer of the auto-generated PDF cover pages. We would like the text of the link to read: [link text]. It should point to this URL:

[URL of feedback form]?ref=

The form expects the URL of the document in Digital Commons as the value of the “ref” parameter.

Optional: Please add this link to all cover pages in the following collections: [list of select collections].

Thank you!

In the case of CUNY, the URL of the web form is http://ols.cuny.edu/academicworks and the form expects a URL to be passed in the link using the “ref” parameter, so bepress needs to know that the full URL is http://ols.cuny.edu/academicworks/?ref= (with “ref” being populated by the document’s URL in Digital Commons) and the link text “How does access to this work benefit you? Let us know!”

That’s it! Users of your institutional repository will now be able to send feedback and the form will automatically generate the referring URL, allowing you to know which document was viewed without straining the user to provide this information.

If you have any questions or run into any problems, feel free to contact me, Allie Verbovetskaya, at alevtina.verbovetskaya@cuny.edu. I’m happy to help!


1 Comment

Leave a comment

Your email address will not be published. Required fields are marked *