Magento provides a simple user account signup page. However, some online stores might want to collect relevant customer information for more targeted and personal interactions with their customers. Some examples of details that could be collected include shoe size, clothing size or favourite colour.
Adding your custom fields on the signup form is not difficult, but it is not trivial either, since one cannot use the Magento backend for the task. As an example of how it can be done, I will demonstrate the addition of a new custom field to the signup form asking new users to enter their favourite ice cream flavour.
We need to make a module to extend the functionality of the customer model. Start by adding the module xml file to the
app/etc/modules/directory. You need to decide on a module name. In this example we will use the Fontis scope, and call the module 'Customer'. Therefore we need to create a file namedFontis_Customer.xmland add the following content:<config> <modules> <Fontis_Customer> <active>true</active> <codePool>local</codePool> </Fontis_Customer> </modules> </config>
Adding the above file means that Magento is now aware of a new custom module. Now, we need to create the module itself, which must be located in the
app/code/local/Fontis/Customerdirectory. Inside this directory, create anetcdirectory and copying the following file inside:app/code/core/Mage/Customer/etc/config.xml
Edit the file and change :
<modules> <Mage_Customer> <version>x.x.x</version> </Mage_Customer> </modules>
to:
<modules> <Fontis_Customer> <version>1.0.0</version> </Fontis_Customer> </modules>
-
This file contains two different
<fieldsets>- one in<config><admin>and one in<config><global>. At the end of the second one, in the<config><global><fieldsets><customer_account>scope, add:<flavour><create>1</create><update>1</update></flavour>
In this example
flavouris the chosen attribute code. The attribute code that you choose here will be important in all the following steps. -
Now we need to add the attribute to the Customer Entity Setup Model. To do this, copy the
getDefaultEntitiesmethod fromapp/code/core/Mage/Customer/Model/Entity/Setup.phpfile to a new file,Model/Entity/Setup.phpin our module. Put the method inside the following class:class Fontis_Customer_Model_Entity_Setup extends Mage_Customer_Model_Entity_Setup
Then add the following code at the end of the attributes array inside the customer arrray:
'flavour' => array( 'label' => 'Ice Cream Flavour', 'visible' => true, 'required' => true, ),
In this case the new attribute is set as compulsory by adding
'required' => true,to the end of that array. If you want the attribute to be optional, remove therequiredlines. -
The new attribute needs to be added to the Magento database. The best way to do this is to tell Magento to insert it for you. You can either create your own script that uses the Magento code or you can just drop the following code into one of your template files:
$setup = new Mage_Eav_Model_Entity_Setup('core_setup'); $setup->addAttribute('customer', 'flavour', array( 'label' => 'Ice Cream Flavour', 'type' => 'varchar', 'input' => 'text', 'visible' => true, 'required' => true, 'position' => 1, ));
A handy place to add the above code is the
<theme>/template/customer/form/register.phtmlfile since it needs to be edited to add a custom field for the new attribute. Make sure the above code is enclosed with<?php ... ?>
To add the attribute (ie. run this code) view the register new customer page. Once you have viewed the page this code can be removed.
In this example the attribute type is set to
varcharand the input is set totext. This needs to be modified to match the requirements of each specific attribute. -
At this point, the attribute is installed and it will show up in the backend. We need to modify the frontend, so that the customers can enter values for the custom attribute. There are two fairly similar phtml files:
<theme>/template/customer/form/register.phtml <theme>/template/customer/form/edit.phtml
As a minimum, you need to add a new text box in the
register.phtmlfile, since that is what customers see on the register page. You can add the same text box in theedit.phtmlfile so that customers can make changes to the original entry that they have made on sign-up. Make sure that the ID and name of the new input text box match the attribute code chosen in step 3. In this case it is 'flavour'. The following shows the sample code that adds a new text box with a label:<div class="input-box"> <label for="flavour"><?php echo $this->__('Favourite Ice Cream Flavour') ?><span class="required">*</span></label><br /> <input type="text" name="flavour" id="flavour" value="<?php echo $this->htmlEscape($this->getFormData()->getFlavour()) ?>" title="<?php echo $this->__('Flavour') ?>" class="required-entry input-text" /> </div>
Address details
If you only want to add fields for address details you are in luck. Those fields are already setup in
the template/customer/form/register.phtml file, but they are disabled by an inactive if statement that so far has not actually been linked to anything else in Magento. Therefore to enable the address related fields you simply need to comment out or delete the following statements:
<?php if($this->getShowAddressFields()): ?>
and
<?php endif; ?>
Note that there are two occurrences of this if statement. One is around the area where the customer actually inputs their data and the other is at the bottom of the file. The first statement shows all the areas for the customer to enter their data and the second statement is around some JavaScript code that sets up the State/Province select.
Removing phone number field
One final issue relates to the telephone number field. By default it is considered a required field and that is hard-coded in the input validation function. If you do not want the telephone field to be mandatory (or any other field for that matter), you need to remove the relevant statement from:
magento/app/code/core/Mage/Customer/Model/Address/Abstract.php
This is the code that needs to be removed from public function validate():
if (!Zend_Validate::is($this->getTelephone(), 'NotEmpty')) { $errors[] = $helper->__('Please enter telephone.'); }
In order to make sure that your Magento installation still works properly after you do an upgrade, rather than changing the core file, the safest option is to copy the above file into the following file structure:
magento/app/code/local/Mage/Customer/Model/Address/Abstract.php
Since files in /local don't get affected when you run upgrades, it means your signup form will work as expected after an upgrade.
Magento Compatibility
| Post originally written for Magento version: | 1.3.2.4 |
| Tested with Magento version(s): | 1.3.2.4 |
Update: Due to a change in core Magento files the technique for adding custom customer attributes had to be modified. This blog post has been updated accordingly, and current instructions have been tested with Magento 1.3.2.4 -- 16/10/2009

Comments
Any body tell me hows it will(Falvor filed) show on admin side.
Hi! I followed your tutorial everything was fine but the values are not getting saved into the backend could please tell me what is the problem
*<?php echo $this->__('Employee Id') ?>
htmlEscape($this->getFormData()->getEmployee_Id()) ?>" title="<?php echo $this->__('Employee Id') ?>" class="input-text validate-employee_id required-entry"/>
Hi! will the same published code works for Magento 1.5.1.0???????
This is a great post, helped me big time! I used this to create a module to add the terms and conditions in the registration page but the data is not being saved. Basically, I created a static block and called it directly from register.phtml.
What I've noticed, is if I edit the edit.phtml file and add:
htmlEscape($this->getCustomer()->getAgreement()) ?>" title="<?php echo $this->__('I AGREE') ?>" class="input-text required-entry" />
Open the account info page, type something in, save, and it will commit to the database.
But the following below will not commit to the database.
//Calling the static block so that it will display under New Registration
<?php echo $this->getLayout()->createBlock('cms/block')->setBlockId('terms_and_agreements')->toHtml();?>
//Created the label and the input box
* <?php echo $this->__('I AGREE') ?>
//Create the input box
htmlEscape($this->getFormData()->getAgreement()) ?>" title="<?php echo $this->__('I AGREE') ?>" class="input-text required-entry" />
What is wrong with my input box, as the value the customer puts in, is not saving to the database.
Using CE 1.5.1 with fontis recaptcha module, and wireframe base default template.
The sql inserts has been added per Brian's additional info, and the rest is followed accordingly to the instructions.
Any help would be great.
Thanks.
I've tried tens of scripts about this issue, and this is the only one actually working. I'm using magento 1.4.2 and I anyone else is interested, you have to add the database rows manually
INSERT INTO `database`.`customer_form_attribute` (`form_code`, `attribute_id`) VALUES ('adminhtml_customer', '542');
INSERT INTO `database`.`customer_form_attribute` (`form_code`, `attribute_id`) VALUES ('customer_account_create', '542');
INSERT INTO `database`.`customer_form_attribute` (`form_code`, `attribute_id`) VALUES ('customer_account_edit', '542');
to make it work in 1.4.2.
Thank you so much!!
ps. do you know how can I control the order of the new attributes, as they display in customer account backend??
what is "542" in ur sql query ?
Hi,
does anybody have this module working in Magento 1.5.1 ? I've been trying for hours and it does not work.
Please upload the whole module (including all files) on some server and put a link here.
I would really appreciate that. Thank you in advanced.
How can I remove the attribute from the back end if I no longer want to use it?
About my previous comment - I figured it out ... I added another line of code into that database table of attributes with value: customer_account_edit + ID of attribute and now it works also at frontend.
Luke
Great tutorial here!!
And also the last comment related to Magento 1.5.0.1 helped me a lot, but I have another problem very similar one:
I have version 1.5.1.0 and everything works fine except, that it does not save custom atribute value on frontend to the database - it works fine on backend - any help pls?
Thx
One more thing to be added in database. Do just as new attribute added in database.
$eavConfig = Mage::getSingleton('eav/config');
$attribute = $eavConfig->getAttribute('customer', 'flavour');
$attribute->setData('used_in_forms', array('customer_account_edit',
'customer_account_create',
'adminhtml_customer'));
$attribute->save();
Hi,
This is a beautifully written tutorial and I've followed it through with no obvious errors for magento 1.5.0.1 ...
BUT...
At step five, upon running the php to add the variable to the db... it says that the variable should now be visible in the back end (I presume this means the customer management pages)... and it isn't...
Furthermore, upon following the tutorial through and registering a new customer with the new variable (existing customer code)... there is still nothing visible in the backend... yet again, no obvious errors.
Did I miss something?
In Magento 1.5 they have added a new MySQL table called:
customer_form_attribute
Basically for each attribute id assigned for the custom fields, you need to add that to this table with the value of "adminhtml_customer". So if you look in the MySQL table:
eav_attribute
look for your attribute codes that are not showing anymore and note the attribute ids. Then make an insert for each id into the customer_form_attribute table with the form_code being "adminhtml_customer" and the "attribute_id" being the actual attribute id that you looked up. So something like:
INSERT INTO `database`.`customer_form_attribute` (`form_code`, `attribute_id`) VALUES ('adminhtml_customer', '542');
542 being the attribute id you looked up. I am sure there is a more elegant solution to adding these to the table, but instead of saying something I thought I would let you know one way to get them to show :)
Thanks for adding this, Brian. It looks like you also need to add a couple more rows to get it to work in 1.5. In addition to the "adminhtml_customer" form_code you will also need to add the "customer_account_create" and the "customer_account_edit" form codes for each attribute_id. So following your example:
INSERT INTO `database`.`customer_form_attribute` (`form_code`, `attribute_id`) VALUES ('adminhtml_customer', '542');
INSERT INTO `database`.`customer_form_attribute` (`form_code`, `attribute_id`) VALUES ('customer_account_create', '542');
INSERT INTO `database`.`customer_form_attribute` (`form_code`, `attribute_id`) VALUES ('customer_account_edit', '542');
Or 'adminhtml_customer_address' for a customer address attribute.
Thanks!! Brian , only you could provide such information! Save my day!
Another way to handle this and make it automated is as follows:
Your config.xml does not need to include a full copy of everything, so change it as follows:
<?xml version="1.0"?>
0.2.0
11
Fontis_Customer
Mage_Core_Model_Resource_Setup
Next, under app/code/local/Fontis/Customer
create a folder call sql and then a folder in that called fontis_customer_setup
so now you have a path like this: app/code/local/Fontis/Customer/sql/fontis_customer_setup
In that folder place a file called mysql4-install-0.2.0.php with the following contents (enclosed in php tags):
$installer = $this;
$installer->startSetup();
//create the new attribute
$setup = new Mage_Eav_Model_Entity_Setup('core_setup');
$setup->addAttribute('customer', 'flavour', array(
'label' => 'Favorite Flavour',
'type' => 'varchar',
'input' => 'text',
'visible' => true,
'required' => true,
'position' => 1,
));
//find out the attribute_id of the newly created attribute
$sql = "SELECT attribute_id FROM ".$this->getTable('eav_attribute')." WHERE attribute_code='flavour'";
$row = Mage::getSingleton('core/resource')->getConnection('core_read')->fetchRow($sql);
//insert the supporting values into customer_form_attribute
$installer->run("
INSERT INTO customer_form_attribute (form_code, attribute_id)
VALUES (
'adminhtml_customer',".$row['attribute_id']."
);
");
$installer->run("
INSERT INTO customer_form_attribute (form_code, attribute_id)
VALUES (
'checkout_register', ".$row['attribute_id']."
);
");
$installer->run("
INSERT INTO customer_form_attribute (form_code, attribute_id)
VALUES (
'customer_account_create', ".$row['attribute_id']."
);
");
$installer->run("
INSERT INTO customer_form_attribute (form_code, attribute_id)
VALUES (
'customer_account_edit', ".$row['attribute_id']."
);
");
$installer->endSetup();
Be sure to get rid of the attribute create code at the beginning of your register.phtml file if you haven't already.
delete the flavour row in your eav_attribute table as well.
Now refresh your home page front-end and you are good to go. The field exists and saves to the database in register and edit and admin backend.
This is a great tutorial! However it no longer works on Magento 1.4.2.0 :( Does anyone have any ideas on how to get this to work with 1.4.2.0?
Great Post - Thank you very much!!
I basically had the same issue that the elements werent stored when inserted via register or edit i.e. the Frontend. The issue was just that my module wasnt properly setup.
In "register.phtml" I entered:
and
In "edit.phtml" I entered:
Works on Magento 1.4.1.1!!!! Finally!!! Now I can go to sleep!
Sorry my horrible english... : (
Thanks so much Denis, just what I needed, I had it all working other than that, and this has fixed it.
Cheers
Usefull post, many thanks!
I get the same problem stated by many. It didn't saved the new field by adding or editing a customer in the frontend. Everythink worked from the backend. Somehow was used the config.xml from Mage/Customer instead of the new one created. I just added the new field on the Mage's one, even if this is not a great solution.
Hello,
I tried the code, but it don't work under Magento 1.4.1...the custom address field was saved only from the account page...
I am having a problem with this in 1.4.1.1,
I have double checked everything but I still cannot get it working on the front end.
The input boxes show up and I can add/edit the value from the admin side, but whenever a customer registers it doesn't add the value to the database.
Does anyone know what this problem may be caused by?
Thanks
did you manage to solve your problem in 1.4? because i have the same problem :(
Works perfectly for me with version 1.4.1.1 - thank you very much... I have one question - do you know how I could now display these variables in an email template ?
Thanks for sharing, works great on 1.4.
Only thing I'm still missing is how to set new attributes to show as dropboxes in admin - like country dropbox for example.
Thanks frome a french guy !!
Here is another how-to dealing with the way to add our custom registration field to the checkout process and pushing it to the customer account on order validation.
The hack is to add the "Flavour" field to the billing address step of the Onepage Checkout.
For this, we need to override the Sales module.
First, follow steps 1. and 2. but reading/using/writing "Sales" instead of "Customer"
Then, in app/local/.../Sales/etc/config.xml, around line 153 :
change
</sales_convert_quote_address>to
Then we need to modify the Sales/Model/Convert/Quote.php file (best practice is to override it in order not to lose our changes on core updates)
Modify the public function addressToOrder() (around line 66) like this :
At last, we need to add the "Flavour" field to the billing step of the One Step Checkout.
Add the following lines to your theme's checkout/onepage/billing.phtml file where you want the "Flavour" field to appear :
Please note that the goal of this how-to is to add a customer-account-wide "Flavour" field rather than an address-wide field (like a "mobile phone" field would be). So, once the "Flavour" field has been set at the customer's first order, it will not be available at checkout for further orders. This explains the use of "isLoggedIn()".
My favourite Ice Cream flavour is Ben & Jerry's chocolate and macadamia nuts!
Tested on Magento 1.4.0.1
I have followed your instructions to add this as a checkout step but the flavour does not appear in the admin, what am I missing? Also is it possible to show Flavour in a customers order email?
This post deals with a thing that didn't get any real answer in this thread : using checkboxes for custom registration fields
This will display a checkbox on the frontend and a "Yes/No" select in the backend.
Let's say we want to know if the customer likes (or not) the chocolate flavour.
At step 3.
Add
<chocolate><create>1</create><update>1</update></chocolate>At step 4.
Add
At step 5.
Add
At step 6.
For register.phtml, add
For edit.phtml, add
We also need to modify the AccountController.php file (best practice is to override it to prevent from loosing modification on core updates)
Around line 583, change
to
An we're done. Tested on Magento 1.4.0.1.
Same problem for me... somene can help us?
I can save new attribute on admin, not in register form...
Another question - Would would be the "proper" way to adjust the input-box widths on the registration form? Apply a CSS class and set the width in CSS?
Thanks!
Applying a CSS class and setting the width using CSS is the commonly accepted method.
Wow - great post! This works flawless (so far, at least).
Two questions:
1) Is there any way to include a product drop-down (for Product Registration purposes)
2) Is there a way to have a date/calendar pop-up similar to the date selection feature in the Admin section, so users can select a date and have it stored in the database?
Thank you!
Brady
As I replied to Brian, to use a drop down for your attributes, you need to use the
source_modelattribute of your attributes to be able to use a drop down. For your particular case (having the drop down populated by products) I'd make the attributes type int which will store the products id. Then, in the custom source model you create use a collection to select the list of products (You might find Chris' post on the efficient use of collections helpful for this) and iterate across the list of products producing an array that is in the same format as the one in the Boolean source file.As for the calendar, the best thing I can suggest is that you look at how the calendar has been achieved in other frontend areas. Briefly, you need to include the calendar block into your page (which has a number of definitions in it), include the calendar JavaScript and the relevant skin CSS files into the page, create an image for the user to click on and then in JavaScript instantiate the calendar.
Thanks for this article. I used it to add some more checkboxes to customer preferences.
At first it wasn't saving anything and I had to modify the controller (newsletter/controllers/ManageController.php) to save the values. Somewhere I read that you don't have to do this, but I found that I did. It was quite simple in my case, just find the action which is saving, in my case saveAction and set the extra fields.
Mage::getSingleton('customer/session')->getCustomer()
->setStoreId(Mage::app()->getStore()->getId())
->setIsSubscribed((boolean)$this->getRequest()->getParam('is_subscribed', false))
->setNewfield((boolean)$this->getRequest()->getParam('newfield', false))
->save();
Of course you have to point the form action to the new controller too ;)
Hi,
alandubs, did you do that to add the ability to let new customer subscribe to more than one newsletter? If yes, could you give more details on how you did it?
Thanks
Didier
Found the problem and why it probably only affects certain users. If you go here:
http://www.magentocommerce.com/wiki/custom_module_with_custom_database_t...
It says this in part of the document:
Note2: It seems that currently, if you use upper case characters in module names (expecting to show word starts since neither - nor _ is allowed)... the install will fail or rather the module will not work. Suggestion: use a single upper case character, at the beginning of the name.
The problem I had was that I named the module like ModuleName_WholesaleCustomer
When I did that everything appeared to work, but on the frontend it was not taking in the new data that people were filling out. So by changing the above to:
Modulename_Wholesalecustomer
and all the values within the files to match the problem is now fixed! Everything works great now! So the just remember that you can only use a capital letter on the first letter, everything else must be lowercase!
So how do we add a dropdown menu (select box) to the create an account form/process?
Say on my Create an account I want to show a select with 11 possible job types and have the user indicate their job category as part of the signup process. Using the process above, how do values for the options and the text for the options get created?
What about checkboxes? Values and text?
What you wrote above is incredibly helpful! Thank you. It would be complete by showing examples of how to create some other form elements.
For clarification, I've phrased the question a little differently and with examples here: http://www.magentocommerce.com/boards/viewthread/73362/
Unfortunately, this is a bit more complicated than it looks, and in fact using other form elements for attributes on customers (and products and most anything else) probably warrants its own blog post that hopefully I can address in the future. In brief, to create a select box for a customer attribute you need to use the source_model attribute of the attribute. Have a look at the way the attribute is handled for the
is_anchorattribute on categories. You can use the same source model for any checkboxes that you want as well. The source file for the attribute isapp/code/core/Mage/Eav/Model/Entity/Attribute/Source/Boolean.php. There are also customer specific source models in theapp/code/core/Mage/Customer/Model/Customer/Attribute/Source/and theapp/code/core/Mage/Customer/Model/Entity/Address/Attribute/Source/directories. You also might need to make some backend models so that the attributes display correctly in the backend. The backend models are displayed in the Backend directories 'next to' the Source directories.Great post! Is there a way to add this as a drop down menu?
L-O
From the backend, no problem to save content of new attribute but impossible to save it from the front-end ?
Have you any idea ?
(I got attribute manager extension installed.)
THanks
To complete what I was saying :
Actually, it's when I want to uncheck the input (which isn't posted in the form, only posted when
checked), that way, the value for the user is always "on".
What about a checkbox input ? I'm not able to get it to work with a checkbox, I got no errors, but it doesn't save the input. I just changed 'input' => 'text' to "checkbox" and changed the output html in both register and edit forms.
I can't find any example of checkbox in the eav_attribute table.
Any help please ?
Can you be so kind to be more clear at point 4?
I got setup.php with the followinf line:
***************************************************************************************************
class Mage_Customer_Model_Entity_Setup extends Mage_Eav_Model_Entity_Setup
{
public function getDefaultEntities()
{
return array(
'customer' => array(
'entity_model' =>'customer/customer',
'table' => 'customer/entity',
'increment_model' => 'eav/entity_increment_numeric',
'increment_per_store' => false,
'attributes' => array(......................................................................
***************************************************************************************************
You say "Put the method inside the following class:", so means at the end of the file to do the following:
****************************************************************************************************
class Fontis_Customer_Model_Entity_Setup extends Mage_Customer_Model_Entity_Setup
{
public function getDefaultEntities()
{
return array(
'flavour' => array(
'label' => 'Ice Cream Flavour',
'visible' => true,
'required' => true,
),
)
}
}
*********************************************************************************************
The comma after the first closing ) should be cancelled?
Thank you
The code should work as is. The comma isn't required and it would be a bit neater to remove it, but functionally it shouldn't make any difference.
Hi Denis,
This works perfect. Thank you.
I wanted to make this field to be saved from one page checkout.
How do I do it?
Post new comment