Select Page

Drupal Commerce Store Setup with Drupal 10

Setting Up a T-Shirt Store with drupal/commerce:^3.0

Drupal Commerce 3.x is optimized for Drupal 10 and introduces improvements in order processing, checkout flows, and tax/shipping handling. Below are the steps to set up your T-shirt store with automatic shipping and state tax calculations.

 

1. Install Drupal & Drupal Commerce

Run the following commands in your terminal to install Drupal and Drupal Commerce 3.x:

composer create-project drupal/recommended-project my_store cd my_store composer require drupal/commerce:^3.0

Enable required modules:

drush en commerce commerce_cart commerce_checkout commerce_store commerce_price commerce_product commerce_order commerce_tax commerce_shipping address -y drush updb

 

 

2. Configure the Store

Go to Commerce → Configuration → Store Settings → Stores and create a store with these settings:

  • Name: Your T-shirt Store
  • Address: 2000 S Mill Ave, Tempe, AZ 85282
  • Currency: USD
  • Default Country: United States

 

 

3. Add Products

Using Drupal Commerce 3 how to Create Product Variation Type (Size Attribute) for a “T-Shirt” product. Add an attribute called Size: Options: SM, MD, LG, XL, 2XL, 3XL

In Drupal Commerce 3.x, you can create a Product Variation Type with a Size attribute for your “T-Shirt” product using the following steps:

3.1 Create a Product Variation Type

  1. Go to Commerce → Configuration → Product Variation Types.
  2. Click “Add Product Variation Type”.
  3. Fill in the fields:
    • Label: T-Shirt Variations
    • ID: tshirt_variation (auto-generated)
    • Order item type: Default
  4. Click “Save”.

3.2 Add the “Size” Attribute

  1. Navigate to Commerce → Configuration → Product Attributes.
  2. Click “Add Product Attribute”.
  3. Fill in the details:
    • Label: Size
    • Attribute type: List (text)
    • Variation types: Select T-Shirt Variations
  4. Click “Save”.

3.3 Add Size Options

  1. After saving, go to the “Add values” section.
  2. Enter the size options one by one:
    • SM
    • MD
    • LG
    • XL
    • 2XL
    • 3XL
  3. Click “Save”.

3.4 Assign the Variation Type to the Product Type

  1. Navigate to Commerce → Configuration → Product Types.
  2. Click “Add Product Type”.
  3. Fill in:
    • Label: T-Shirt
    • Variation type: T-Shirt Variations
  4. Click “Save”.

Now, when adding a T-shirt product, you can create variations with different sizes!

 

 

4. Set Up Taxes for All 50 US States

Drupal Commerce 3.x has better tax integration. You can manually configure tax rates or use an external provider.

4.1 Enable Tax Calculation

  1. Navigate to Commerce → Configuration → Taxes.
  2. Click Add Tax Rate → Select “Sales Tax”.
  3. Choose US State-based Taxation.
  4. Set tax rates manually for all 50 states or use a tax provider like Avalara/TaxJar.

4.2 Automatic Tax Calculation (Optional)

For automatic tax calculation, install a tax provider module:

composer require drupal/commerce_avatax

Then, configure it under Commerce → Configuration → Taxes.

 

 

5. Configure Automatic Shipping Calculation

5.1 Install and Enable Commerce Shipping

composer require drupal/commerce_shipping drush en commerce_shipping -y

5.2 Configure Shipping

  1. Go to Commerce → Configuration → Shipping.
  2. Click “Add Shipping Method”.
  3. Set Origin Address as:
    • 2000 S Mill Ave, Tempe, AZ 85282
  4. Choose Flat Rate or install real-time shipping providers.

5.3 Real-time Shipping Rates

To enable FedEx, UPS, or USPS, install their modules:

composer require drupal/commerce_fedex drupal/commerce_ups drupal/commerce_usps

Then configure API credentials under Commerce → Configuration → Shipping.

 

 

6. Test Your Store

  1. Add a T-shirt to the cart.
  2. Proceed to checkout.
  3. Verify:
    • Taxes apply based on the shipping address.
    • Shipping costs are calculated from Tempe, AZ.

Your Drupal Commerce T-shirt store is now ready!

VIM Cheatsheet

vim {file} — Vi IMproved, a programmers text editor

Commands
i – insert mode
esc – get out of insert mode
:{number} – go to that line number 
:q
 – quit
:q! – force quit (no save)
:e! – discard edits to last saved state
:w – save document (write)
:wq – save and quit document
:ZZ – save and quit document

Moving Around
h, j, k, l — move cursor like arrow keys
$ – move cursor to end of current line
0 – move cursor to start of current line
w – move to next word
b – go back a word
ctrl f – page down
ctrl b – page up

Copy and Paste
y
 – yank or copy
yw – copy word
yy – copy whole line
#y – copy # of words. Example 5y (copy 5 words)
#yy – copy # of lines. Example 5yy (copy 5 lines)
p – paste

Undo and Delete
u – undo
x
 – delete current letter
dd – delete whole line
dw
 – delete next word
db – delete previous word
cw – delete next word and go into insert mode
cc – delete line and go into insert mode

Visual Mode
v – activate visual mode

Additional Shortcuts
shift i – go to start of curent line start insert mode
shift a – go to end of current line start insert mode
d arrowletter – delete word direction you point

Getting Started with React

React

Installation

  1. Install Node
  2. Install Create React App

Create React App Installation

npm install -g create-react-app

 

Create Project

Will create the project folder and all the packages and tools.

create-react-app projectname
cd projectname
npm start

 

AngularJS Form Validation

Form validation is an important part of web development. The user experience of your online forms will leave an impression on your visitors so it is important that you build great forms on your website. We will apply AngularJS to an existing online form.

 

Initial Form

Use the following HTML which uses Bootstrap CSS for formatting as a starting point. After you work through this example you can apply the changes to an existing form.

<div class="form-container">
<form name="myform" action="" method="post">
 
 <div class="form-group">
 <label for="firstname">First Name &#42;</label>
 <input type="text" name="firstname" placeholder="First Name">
 </div><!-- .form-group -->
 
 <div class="form-group">
 <label for="lastname">Last Name &#42;</label>
 <input type="text" name="lastname" placeholder="Last Name">
 </div><!-- .form-group -->
 
 <div class="form-group">
 <label for="email">Email Address &#42;</label>
 <input type="text" name="email" placeholder="Email Address">
 </div><!-- .form-group -->
 
 <button type="submit" class="btn btn-default">Submit</button>
</form>
</div><!-- #form-container -->

 

Add AngularJS to your page.

Add AngularJS to the bottom of your page. I also added in the Bootstrap CDN for CSS styling. The ng-app directive tells AngularJS that this is the root element of the AngularJS application. We will apply this to the div outside our form. The “form-container” class is optional we are using it for our demo. You will want to apply ng-app to a div outside your existing form.

<div class="form-container" ng-app>
<form ...>
  ...
</form>
</div><!-- #form-container -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>

 

Add form validation.

Apply the following angular directives for form validation.

The ng-required directive indicates that a field is required. If a required field has no value the form will automatically have an ng-invalid class applied until the requirements are met.

  <div class="form-group">
    <label for="firstname">First Name &#42;</label>
    <input type="text" name="firstname" placeholder="First Name"
      ng-required="true">
  </div><!-- .form-group -->

 

Test form values

The ng-model directive binds an input, select, textarea (or custom form control) value to angular. Use the same field name and append user.fieldname to the front to bind it to the {{user}} data object which we will use to view our form values.

  <div class="form-group">
    <label for="firstname">First Name &#42;</label>
    <input type="text" name="firstname" placeholder="First Name"
      ng-model="user.firstname"
      ng-required="true">
  </div><!-- .form-group -->

For testing we add an alert div to output our {{user}} data which will display our ng-model form values. Angular uses the double curly brackets to display data. Add this above the submit button.

 <p class="alert alert-warning">Output: {{user}}</p>

 

Validate the email address

The ng-pattern directive is used on the email field for regular expression matching to validate the email address.

  <div class="form-group">
    <label for="email">Email Address &#42;</label>
    <input type="text" name="email" placeholder="Email Address"
      ng-model="user.email"
      ng-required="true"
      ng-pattern="/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/">
  </div><!-- .form-group -->

 

Disable the submit button until the form passes validation

The ng-disabled directive is applied to our submit button and will remain disabled until all the form validation passes.

  <button type="submit" class="btn btn-default" ng-disabled="myform.$invalid">Submit</button>

 

Final touches

We are adding additional user prompts to let the user know there is missing field data.

  • The ng-show directive will display this element until the requirements indicated in the property are met.
  • The field was marked as required in the previous step by ng-required=”true” property. The myform.firstname.$invalid condition will return true until there is a value added into the field.
  • We also added a $touched condition which means the field has been activated. This will not return true until the cursor has entered the field.
 <div class="form-group">
 <label for="firstname">First Name &#42;</label>
 <input type="text" name="firstname" placeholder="First Name"
 ng-model="user.firstname"
 ng-required="true">
 <div ng-show="myform.firstname.$invalid && myform.firstname.$touched"
 class="alert alert-warning">You must fill out your first name.</div>
 </div><!-- .form-group -->

 

Completed Form

Here is the code for the completed form.

<div class="form-container" ng-app>
<form name="myform" action="" method="post">
 
 <div class="form-group">
 <label for="firstname">First Name &#42;</label>
 <input type="text" name="firstname" placeholder="First Name"
 ng-model="user.firstname"
 ng-required="true">
 <div ng-show="myform.firstname.$invalid && myform.firstname.$touched"
 class="alert alert-warning">You must fill out your first name.</div>
 </div><!-- .form-group -->
 
 <div class="form-group">
 <label for="lastname">Last Name &#42;</label>
 <input type="text" name="lastname" placeholder="Last Name"
 ng-model="user.lastname"
 ng-required="true">
 <div ng-show="myform.lastname.$invalid && myform.lastname.$touched" 
 class="alert alert-warning">You must fill out your last name.</div>
 </div><!-- .form-group -->
 
 <div class="form-group">
 <label for="email">Email Address &#42;</label>
 <input type="text" name="email" placeholder="Email Address"
 ng-model="user.email"
 ng-required="true"
 ng-pattern="/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/">
 <div ng-show="myform.email.$invalid && myform.email.$touched" 
 class="alert alert-warning">This must be a valid email.</div>
 </div><!-- .form-group -->
 
 <!-- Display Form Values for Testing !!!Delete after testing!!! -->
 <p class="alert alert-warning">Output: {{user}}</p>
 
 <button type="submit" class="btn btn-default" ng-disabled="myform.$invalid">Submit</button>
</form>
</div><!-- #form-container -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>

Drupal 7 Security Configuration

Prevent Browser caching
Put this at the top of your theme template.php file:

header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");

 

Download and enable the SecKit module:
https://www.drupal.org/project/seckit
There are some nice default settings. We can review tweak these settings as part of a security review when we have more time.

HTML Email Signatures

Creating an HTML email signature can be a deceivingly difficult process. After having to tackle this issue a number of times this is the best method I have found to get the correct formatting.

  1. Start with a clean HTML file. You only want the divs for your signature.
  2. Save to your desktop and view it in your browser.
  3. Use in-line styles and link to external images for any logos or graphics.
  4. When the format is correct you want to use a browser on Windows and Outlook.
  5. Select the formatted details in your browser then copy and paste it into Outlook. As you know Microsoft does preserve a lot of hidden formatting when you cut and paste into their products. You may have experience headaches with Word doing a lot of crazy formatting. But in this case it is helping us preserve the formatting for your signature.
  6. Send a test email out with your updated signature and view it in various email clients to confirm the formatting is correct.

Some Drupal SEO Considerations

Some SEO features you may want to include in your Drupal website.  Here are a few notes I took after conducting an SEO review on one of my websites.

Title Tag
A title tag is the main text that describes an online document. Title elements have long been considered one of the most important on-page SEO elements (the most important being overall content), and appear in three key places: browsers, search engine results pages, and external websites.

Here are my personal preferences for Configuration > Site information:

  • Site name: Project Name | ASU
    The page title will the render as [Page Title] | Project Name | ASU.

Metatag Description and Keywords
While most search engines now ignore the metatag keywords but the page description is still very important.  I add a teaser field to a node which I use to generate this content. Install the Metatag module.

  • Install the Metatag module with the follow submodules enabled: Metatag, Metatag verification (see below)
  • Click configuration on Metatag.
    • Global > Content select the Override link.
    • Set the Description field to your custom field in my case it is [node:field_news_teaser].
  • Site Ownership Verification
    • Enable the module Metatag verification (part of the Metatag package)
    • Follow the HOWTO links available on the documentation: https://www.drupal.org/node/1774342

XML Sitemap
The XML sitemap module creates a sitemap that conforms to the sitemaps.org specification. This helps search engines to more intelligently crawl a website and keep their results up to date. The sitemap created by the module can be automatically submitted to Ask, Google, Bing (formerly Windows Live Search), and Yahoo! search engines.

  • Enable the following modules included in the package: XML sitemap, XML sitemap custom, XML sitemap engines, XML sitemap menu, XML sitemap node
  • Update your content types to rank the priority of each: Structure > Content Types > Click Edit on your content type you want to be included in the site map.
  • On the bottom configuration tabs you will click XML sitemap. Use the following settings
    • Inclusion: Included
      This indicates that this content type will be included in the site map.
    • Default priority: 0.5 normal
      The priority is the importance value of your content. Basic pages I leave at the default 0.5 normal setting. News I rank at that same value. On one website I rank Research Centers at 0.8 because this content type is the most important for the website. The default setting for the home page is 1.0 which is the highest importance.
  • Configuration Settings: Go to Configuration > Search and Metadata Section > XML sitemap and review the settings. If everything looks good you can click Rebuild Links and run that to get your initial sitemap built.
  • Click the Search Engines tab and click the Bing and Google checkboxes and save the submission settings.

Copy Drupal site to local Dev

Local Development Environment: MAMP Pro

  1. Download a copy of your drupal public folder to your computer.
  2. Export a copy of your database.
  3. Create the database on your local machine.  Import your database from the file you just downloaded. For larger databases please reference my blog post about how to increase the memory allowance on MAMP.
  4. Copy the drupal root folder into your MAMP htdocs folder. Rename it to “dev.websitename” to keep things organized.
  5. Create your MAMP Host entries so your site will load at “http://websitename.local:8888”.
  6. Files to update:
    • .htaccess – update all references to the live URL and update them to your local URL.
    • settings.php – update all references to the live URL to your local URL. Set $cookie_domain to “localhost”.
      • update database settings
      • $base_url = “http://websitename.local:8888”
      • $cookie_domain = “localhost”
  7. Launch your site and everything should be working as expected.