Can you customize a contribution page?
We have some examples of how to customize Contribution forms in our iATS Payments extension. Essentially the recipe involves: buildForm hooks, custom templates and JavaScript. I'll try and explain below how they all tie together:


buildForm hook


https://github.com/iATSPayments/com.iatspayments.civicrm/blob/master/iats.php#L285

Here we check what form we're on (event, contribution, backend, frontend, etc.). For the main contribution page we're:

case 'CRM_Contribute_Form_Contribution_Main':
  $fname = 'iats_civicrm_buildForm_Contribution_Frontend';



function iats_civicrm_buildForm_Contribution_Frontend(&amp;$form) {


https://github.com/iATSPayments/com.iatspayments.civicrm/blob/master/iats.php#L781

Let's say we have ACHEFT (debit) payment processor and currency is CAD - and we want to customize the contribution form - to use Canadian language for direct debit, display Canadian instructions and help the user fill out the fields by displaying a Canadian cheque image. 

if (!empty($acheft[$form-&gt;_paymentProcessor['id']])){  
  iats_acheft_form_customize($form);



function iats_acheft_form_customize($form) {


https://github.com/iATSPayments/com.iatspayments.civicrm/blob/master/iats.php#L612

$fname = 'iats_acheft_form_customize_'.$currency;



function iats_acheft_form_customize_CAD($form) {


https://github.com/iATSPayments/com.iatspayments.civicrm/blob/master/iats.php#L660

Here we addElement-s, addRule-s; setLabel-s:

 $form-&gt;addElement('text', 'cad_bank_number', ts('Bank Number (3 digits)'));
 $form-&gt;addRule('cad_bank_number', ts('%1 must be of length 3.', array(1 =&gt; ts('Bank Number'))), 'rangelength', array(3,3));
 $element-&gt;setLabel(ts('Bank Number + Transit Number'));


and inject the CAD template:  

CRM_Core_Region::instance('billing-block')-&gt;add(array(
    'template' =&gt; 'CRM/iATS/BillingBlockDirectDebitExtra_CAD.tpl'
  ));



In that https://github.com/iATSPayments/com.iatspayments.civicrm/blob/master/templates/CRM/iATS/BillingBlockDirectDebitExtra_CAD.tpl


We load js (to move the fields around):

&lt;script type="text/javascript" src="{crmResURL ext=com.iatspayments.civicrm file=js/dd_acheft.js}"&gt;&lt;/script&gt;

&lt;script type="text/javascript" src="{crmResURL ext=com.iatspayments.civicrm file=js/dd_cad.js}"&gt;&lt;/script&gt;


We inject a CAD Cheque image:  

&lt;div class="content"&gt;&lt;img width=500 height=303 src="{crmResURL ext=com.iatspayments.civicrm file=templates/CRM/iATS/CDN_cheque_500x.jpg}"&gt;&lt;/div&gt;


and render the fields we just created - e.g.:

  &lt;div class="crm-section cad-transit-number-section"&gt;
  &lt;div class="label"&gt;{$form.cad_transit_number.label}&lt;/div&gt;
  &lt;div class="content"&gt;{$form.cad_transit_number.html}&lt;/div&gt;


The js files are located here:

https://github.com/iATSPayments/com.iatspayments.civicrm/blob/master/js/dd_acheft.js
https://github.com/iATSPayments/com.iatspayments.civicrm/blob/master/js/dd_cad.js


In them you we do quite a few things - like move fields around and run some validations on the bank number and the transit numbers that were entered. 

Hopefully these examples will be useful to you! I realize it's probably more than you bargained for! But once you get these techniques under control - you'll be able to gain full control over all your CiviCRM form pages. 

End result for this example: