All posts by Everett - TipsFor.us

Comparison of Online Email Marketing Companies

If you work on commercial web-sites, eventually you find the need to add email marketing services such as newsletters and special advertisements. The article compares 4 services: Campaign Monitor vs. Constant Contact vs. Mail Chimp vs. Topica in several categories, primarily templating abilities, the usability, and the documentation. This review does not cover the reporting capabilities of these products, but all of them offer the standard set of success metrics.

DISCLAIMER: The review only reflects my own experience using each product for about an hour each; I’m not affiliated with any of these companies.

Campaign Monitor

Price: Pay as you go: a flat delivery fee of $5, plus 1 cent for each recipient.

Templates: HIGH MARKS. You can get started with a library of their own templates, and you can easily customize the HTML and CSS via their custom tags, e.g.
<$title$>
Or
<$title link='true' default='Enter Title Here'$>
They provide a good cheatsheet and plenty of template samples.

Limits: only 10 custom fields allowed on email forms.

API: HIGHEST MARKS. Very well documented, code samples of each method in various languages. Like Mail Chimp, Campaign Monitor also offers plugins to various CMS’s including WordPress, Drupal, Joomla, Expression Engine etc.

Demo: Yep, try it totally free. You only pay when you send an email.

Summary: Very easy to use, offers one of the most flexible templating systems available with a lot of samples and a really helpful CSS comparison guide for styling emails for different email clients. Campaign Monitor distinguishes itself from Mail Chimp with its ability to resell distributions (you can set up campaigns for multiple clients through one account) and its payment structure.

Constant Contact

Price: uses pricing tiers based on the max number of emails you will send. Starts at $15 a month for up to 500 emails/month; there are also limits to the number of images you can host in your account.

Templates: Somewhat limited… the UI felt boxy, and although they support custom HTML/CSS, the pseudo code they used did not resemble anything I’d seen before: it uses XML-looking tags, so they are difficult to see once they are actually used alongside HTML. Clicking on the help links dumped out to a PDF page… but the PDF never loaded, so I had to email customer service before I could check out the Advanced Editor’s Guide and see how they handle templating.

Limits: varies per subscription level; the site itself is not friendly with Safari, and there were problems accessing their PDF docs.

API: Yes, but it’s a little hard to find: http://developer.constantcontact.com/. The interface is very XML centered (which is not PHP’s strong suit) and the docs are a bit hard to navigate and don’t include many examples. As expected, you can Import Outlook or csv files to populate your contact list.

Demo: 60 days with full support.

Summary:
The strengths are that this company also does Online Surveys and Event Marketing in addition to the Email Marketing, and they get HIGH MARKS for customer service — a representative called me to follow up and sent me an email with links for everything I asked for. But I have to take off points for limiting special characters in the account passwords (If you’re gonna pretend like you care about my password strength by putting a Password Strength widget on your form, then you gotta follow through and allow special characters in the passwords!). Their representative assured me that their email templates were tested and functional across all browsers, but their control panel doesn’t work with Safari and there were problems accessing the PDF documents — even their little helpful survey widget asking “how you doing?” failed to submit properly, probably due to some browser-specific Javascript.

Mail Chimp

Price: HIGHEST MARKS! 3 options:

  • Monthly (50k subscribers): starts at $380, up to 600k sends.
  • Pay as You Go (you buy “email credits”, starting at 3 cents per email)
  • Forever Free (up to 3k sends/mo, list less than 500 contacts, emails include affiliate badge in footer)

Limits:
no built-in surveys, but there is a built-in integration with SurveyGizmo.

API: Yes! HIGH MARKS! Documented for PHP, with some code samples in many languages. There are plugins for Drupal, FoxyCart, ExpressionEngine, etc.

Templates: HIGH MARKS! Yep, you can choose from their starter templates or use your own HTML/CSS using tags like this:
*|MC:SUBJECT|*
The tags even support if statements and formatting options. Template Language documentation is here: http://www.mailchimp.com/resources/email-template-language

Demo: Yep, free to try for as long as you’d like.

Summary: High marks all the way around. Flexible pricing options, custom templates, thorough API, and helpful videos. This is a very good product.

Topica

Price: starts at $49.95 for up to 1,000 names… but the pricing page is hard to find.

Templates: You can use your own HTML, CSS, and images, but you can’t store them on their server — it’s a bit difficult to see where to do this, exactly: go straight to the “Campaigns” menu and choose to use “No Template”. You can use up to 15 custom tokens (configurable under “Preferences”), e.g. ${token1}, but heavy use of tokens is discouraged because it increases database load.

API: Yes, it’s SOAP based, but (again) it’s hard to find: http://topica.com/services/. As expected, you can do bulk imports and bulk exports of contacts or audience data.

Demo: Limited 14 day “demo” is available, but it’s really an “opt-out” purchase requiring credit card authorization “If you do not cancel during your trial period, your account will remain active and be charged a minimum monthly fee of $49.95” as well as $0.01 per name in your database if you use more than your selected capacity.

Summary: Topica gets HIGH MARKS for customer service, and their biggest strength is that they’ve been around a long time and their servers are said to be in the “good-graces” of most ISPs and, like Constant Contact, they got people available to take your calls. They have reasonable customer service: questions were answered during normal times. However, the site is hard to navigate, it has some browser display issues and even a couple 404 errors in the control panel (!), and searches for documentation tended to funnel me back to contact their sales/support people instead of to actual pages. And personally, I’m not too keen on an opt-out purchase agreement in order to “demo” the software.

Summary

In summary, I’d say that MailChimp and Campaign Monitor were the best I looked at: both offered very flexible templates, thorough examples, and a flexible, well-documented API. I’d have to say that Campaign Monitor code samples are amongst the best I’ve seen, but Mail Chimp has excellent documentation and an equally flexible templating system. Topica came across as a bit boxy and overpriced for smaller campaigns given its features. Constant Contact was somewhere in the middle… I know it’s a popular option, but browser issues in the control panel and the lack of a sensibly-documented API make it an unattractive option for me.

Writing Custom PHP Snippets for MODx (part VII)

This article and tutorial video takes on how to add custom PHP scripts (known as Snippets) to the MODx content management system. This covers MODx Evolution (version 1.0 and before), but many of these methods and principles are applicable to MODx Revolution (version 2.0) and PHP coding in general.

A video used to be embedded here but the service that it was hosted on has shut down.
Watch Video @ Blip.Tv

Adding a Snippet

MODx newcomers are sometimes confused as to where to upload the PHP files… YOU DON’T UPLOAD IT. You paste it into a database record. You can reference files on the file system, but you don’t have to.

1. To add a Snippet from the MODx (v1) manager go to Elements –> Manage Elements –> Snippets then paste in your PHP code.
2. Be sure to give it a unique name (I recommend avoiding spaces in the name)
3. Give it a category: this will make your Snippet easier to find in the manager.

Recommended Components of a PHP Snippet

This applies to ANY code you write, but for the record, please include the following documentation as comments in your Snippet:
1. SUMMARY: a sentence describing what the Snippet does.
2. INPUT: list any input variables the Snippet can accept. It’s good to note the data type (e.g. integer/string), whether or not they are required, or whether or not they have a default value.
3. OUTPUT: list any special output created by the Snippet. Usually it’ll just be HTML, but it’s good to note any external actions (e.g. whether it updates a database row).
4. EXAMPLE: give an example of how the Snippet should be called.

Sample Comment Block



Coding Suggestions and Rules of Thumb

1. Develop your Interface before you code: that bit about adding comments isn’t just for other users, it can help you determine how you want to be able to interact with your code. Coding to an interface is good way of establishing goals and structure before you even start writing the actual code.
2. Initialize your variables: This cuts down on the possibility of security exploits, bugs, and it makes your code easier to read, e.g.:
$output = '';
$garfield_characters_array = array();

3. Sanitize your input: if you are getting any user entered data (e.g. anything out of the $_POST or $_GET array), sanitize the data using regular expressions and if/then statements. Make SURE you have eliminated any possibility that the data is something other than what your program expects.
4. Test as you Go: PHP doesn’t have a built-in debugger, so don’t go too long without checking to see if your code still “compiles” (technically, you should check to see if it has a valid syntax and if it executes). Checking often will help you track down where you made a mistake.
5. Use Good Variable and Function Names: be descriptive. Don’t become a member of the hated “ASCII Preservation Society”. Besides, if you use unique variable names, it becomes MUCH easier to search for instances of that variable, and you’re less likely to have variable collisions.
6. Group your Code into Units: In a word, use functions that fit on the page. If you can SEE it, you’re less likely to UNDERSTAND IT. Chapters of uninterrupted code are hard to debug and test.
7. Reuse your Code: if there are cases in your code where you’re copying and pasting identical or NEARLY identical parts, then it’s time to relegate that code to its own separate function.
8. Log your Errors: if something goes wrong, let your users know about it. It’s a wonderful thing to use the MODx logging function.
9. DO NOT MIX HTML and PHP! There are a few cases where where this is acceptable, but it is good architectural design to separate your view (i.e. your HTML) from your logic. If you have to edit your PHP code to change div tags or CSS classes, then you probably did something wrong. Instead, use MODx Chunks to format Snippet output; your code will be MUCH cleaner as a result and MUCH easier to maintain.

Including Files from the File System

If you write anything more than simple Snippets, you’ll want to put your PHP file(s) on the file system and reference them from the Snippet stored in the MODx database. You can do this by including a standard include or require statement, e.g.

include($modx->config['base_path'].'assets/snippets/mysnippet/include_me.php');

The standard MODx location would be in your own folder within the /assets/snippets directory.

Things to Remember When Including Files and Using Functions

1. Variable Scope: the $modx super-object and the methods that go along with it will not remain in scope within a funciton; use the global to ensure that the globally scoped $modx variable instance is used inside the function. Compare the two instances of the same API call:
// INSIDE a function
function inside_a_function($chunk_name,$garfield_characters_array)
{
global $modx;
$output = $modx->parseChunk($chunk_name, $garfield_characters_array, '[+', '+]');
return $output;
}

// Or OUTSIDE a function
$output = $modx->parseChunk($chunk_name, $garfield_characters_array, '[+', '+]');

2. You can’t return a value directly from an included file: because MODx treats Snippets as functions, it’s considered good form to always return a value, e.g. “return $output;” or “return TRUE;” but this MUST be returned from the original Snippet in the database; if you return output from the included file, you’ll have to return it again from the original database Snippet code. See the video for this quirk in action.
3. Take advantage of the File System: if you are developing stand-alone PHP files, you can use the bash terminal (on Linux or OS X machines) to test the PHP syntax. Simply navigate to the directory where your file is and type:
php -l name_of_your_file.php

Forgot your MODx Password? You can reset it…

I have *cough* never forgotten my password to anything because I followed Brian’s excellent advice about storing passwords, but just in case some of you have, I thought I’d help you out.

If you have access to your MySQL database, you can still log into the MODx manager.
If you have access to your MySQL database, you can still log into the MODx manager.

First off, if you are locked out of your MODx manager, you can use the standard link on the manager page to email you your password, but I’m outlining how to do this in the event that you either didn’t enter a valid email address or you aren’t receiving your emails somehow. There are two things I’m going to outline:

  1. Resetting your MODx manager password
  2. Adding a new MODx manager user

WARNING: Both options require that you have read/write access to the MySQL database where the MODx information is installed. PROCEED WITH CAUTION… THIS REQUIRES DATABASE EDITS.

Option 1 is nicely outlined by this article at Lucid Green: How to get into MODx when your blocked or lost your password. The article is a bit dated (2006), but it’s still valid… to summarize, do the following:

Resetting Your MODx Manager Password

We’re going to do two things here: change your password, and clear any blocks on your manager user.

  1. Login to your site’s database (e.g. using phpMyAdmin).
  2. Find the table modx_manager_users –in phpMyAdmin, find the table in the list on the left.
    phpMyAdmin lists all tables on the left-hand side
    phpMyAdmin lists all tables on the left-hand side

    NOTE: the modx_ is the default table prefix… your installation may use a different prefix, or it may use no prefix. If you honestly can’t locate the table, you may have to resort to the following query to find the table: SHOW TABLES LIKE '%manager_users';

    Can't find the table? SHOW TABLES LIKE ...
    Can't find the table? SHOW TABLES WHERE ...

    Type that at the MySQL prompt and any tables with a name ending in “manager_users” will be shown.

  3. Select your user from the list — in phpMyAdmin you can click the “Browse” tab to browse the rows in each table. Choose to CHANGE or EDIT the row.
    Edit your user
    Edit your user
  4. Select the MD5 function to operate on the password column. In phpMyAdmin, when you edit a record, you can use functions to operate on each column. Once you’ve selected to use the MD5 function, you can type your new password normally.
    Make sure you use the MD5 function!
    Make sure you use the MD5 function!

    If you are doing this via the MySQL command line, the actual query we execute looks something like this:
    UPDATE `your_db`.`modx_manager_users` SET `password` = MD5( 'changeme' ) WHERE `modx_manager_users`.`id` =1 LIMIT 1 ;

    NOTE: if you execute this query at the command line, you must type apostrophes to delineate your password (they will not be included as part of the password). If you are doing this via phpMyAdmin, do NOT type the apostrophes.

  5. Save the changes to the row.
  6. Please note the id for the row that you just edited… you may need it.
  7. Go to the modx_user_attributes table and find your manager user and edit this row (here’s where it’s handy to have that id from the above steps.
  8. Change only the following items then save the row:
    * Set “blockeduntil” to zero (0).
    * Set failedlogincount to zero (0).
    Remove blocks on your user
    Remove blocks on your user

    On the MySQL command line, your query looks something like this:
    UPDATE `your_db`.`modx_user_attributes` SET `blockeduntil` = '0',`failedlogincount` = '0' WHERE `modx_user_attributes`.`id` =1 LIMIT 1 ;
  9. You should now be done… head over to yourdomain.com/manager and login using your new password.

Adding a New MODx Manager User

This is a bit more devious, but the commands aren’t much different than the above, except that we are INSERTING rows into 2 tables instead of UPDATING them. There are many times I’ve needed to “let myself in” using this technique…

  1. As above, login to your site’s database (e.g. using phpMyAdmin).
  2. As above, find the table modx_manager_users –in phpMyAdmin, find the table in the list on the left. (If you have trouble finding the table, see the tip in step #2 above).
  3. Instead of updating an existing record, we are going to create one — in phpMyAdmin, click the “INSERT” tab. Be sure that you do the following:
    * type a valid username (usually, this is one word, lowercase)
    * type a valid password (use the MD5 function!)
    * Leave the id field blank (it will auto-increment).
    * Select “MD5” as the function for the password field (don’t forget!)
    * Leave the “Ignore” box checked — phpMyAdmin allows you to insert a couple rows at once, but we only need to insert one.
    Create a new User
    Create a new User

    Then click Go to insert the new record.

    The actual MySQL query used here is something like this:
    INSERT INTO `your_db`.`modx_manager_users` (
    `username` ,
    `password`
    )
    VALUES (
    'everett', MD5( 'changeme' )
    );

  4. Remember the id of the newly inserted user! You’ll need it — phpMyAdmin shows it after the row was inserted. If you misplaced it, you can simply browse the table and find your user — remember the id!
    The new User's ID is shown here
    The new User's ID is shown here
  5. Go to the modx_user_attributes table and insert a new row:
    Add the following values:
    * id LEAVE BLANK. It will auto-increment.
    * internalKey should also be equal to the your user id from step 4.
    * role = 1 (for manager users)

    The actual query looks something like this:
    INSERT INTO `your_db`.`modx_user_attributes` (`internalKey` ,
    `role`
    )
    VALUES (
    '9', '1'
    );

  6. That’s it. You should now be able to use that username and password to login into your MODx manager at www.yourdomain.com/manager

Securing a Linux Server: SSH and Brute-Force Attacks

If you have a web server, then you are the target of many possible attacks. *ANY* port you have open on that server can be exploited, so you if you value your uptime and your data, you need to secure it. This article focuses on locking down your SSH configuration and user permissions.

If you’ve had your server online for a while without locking down your SSH configuration, have a look at this file: /var/log/secure and see if you’ve got a lot of connection attempts.

This is what a brute-force attack looks like:

[prompt]$ sudo less /var/log/secure
May 31 22:42:12 yourdomain sshd[25711]: Failed password for invalid user alberto from 190.2.35.25
port 32976 ssh2
May 31 22:42:12 yourdomain sshd[25712]: Connection closed by 190.2.35.25
May 31 22:46:11 yourdomain sshd[25714]: Connection closed by 190.2.35.25
May 31 22:56:46 yourdomain sshd[25717]: Invalid user neil from 190.2.35.25
May 31 22:57:10 yourdomain sshd[25717]: reverse mapping checking getaddrinfo for customer-static.someisp.com failed - POSSIBLE BREAK-IN ATTEMPT!

Using Geobytes (or a similar IP address locator), I can see that some hacker-bot in Argentina was guessing both usernames (e.g. alberto, neil) and passwords every few seconds. F*#K!!

The Solution

Here’s what the solution to this problem entails:

  1. Add users for each person accessing the server.
  2. Create a password for those users.
  3. Fly to Argentina and show Sancho I got something for his punk-ass. Just kidding… are you still paying attention?
  4. Add the necessary user(s) to the sudoers file. You don’t want anyone to have direct root access, so this file defines who gets sudo privileges.
  5. Create a public/private ssh key to use in logins.
  6. Install the public key(s) on the server. This will enable the server to recognize the owner of the private key (i.e. you).
  7. Turn off Password Authentication
  8. Disable Root Access

Creating an SSH Key on your Desktop Machine

Keys come in pairs: a public key and a private key. You’ll keep your private key on your machine (in a secure place), the public key you upload to the servers you want to connect to.

You can use different algorithms to generate the key; this shows you how to do it using the DSA algorithm, which is considered more secure (as of this writing).

Open your Terminal and type the following, then just press enter for the default file location. (OS X users can just open their Terminal. Windows users will have to use Cygwin or Putty).

* Do a man ssh-keygen on your machine to see if you require different options to create a dsa key.


[prompt]$ ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/Users/youruser/.ssh/id_dsa):

Type a passphrase (twice).


Enter passphrase (empty for no passphrase):
Enter same passphrase again:

And now you get something like this output:


Your identification has been saved in /Users/youruser/.ssh/test.
Your public key has been saved in /Users/youruser/.ssh/test.pub.
The key fingerprint is:
12:34:56:78:01:23:ab:a7:42:2b:46:5a:3f:fc:4c:ca youruser@ComputerName
The key's randomart image is:


+--[ DSA 1024]----+
| o o++o |
| o+ . oo.. |
|++.o .. |
|*o. + . . |
|+. . * S |
| E o . |
| |
| |
| |
+-----------------+

The ASCII art thing is a new feature, allowing folks to visually identify different keys.

For more information about SSH on OS X, please refer to Dave Dribin’s excellent blog:
ssh-agent on Mac OS X 10.5 (Leopard)

Back on your Web Server

Now that you’ve created your public and private key on your desktop machine, you need to head over to your web server and make some changes.

1. Log into your web server and create users

If you are still logging in as the root user, you need to create other users:

Create a user:
adduser your_username
Create a password for the user:
passwd your_username

Test logging in as this user now. From your desktop machine, try
ssh your_username@your_webserver.com

2. Give One User Sudo Privileges

Now that you have a user other than the root user, you should lock down the root user and push root privileges to the sudo command. The goal here will to disable root logins entirely.

You will need to switch to the root account to perform the following. You can either login as the root account from your desktop machine, or switch to the root account by using the Switch User command (su):
[prompt]$su - root

You grant sudo privileges to your users by editing the sudoers file… but you can’t simply edit that file. You must use the visudo command. This is a very special variant of the VI text editor which is designed for a single purpose: to edit the sudoers file. The security of your entire server can be compromised by this single file, so the visudo command ensures that any editing of this file never allows it to be in a state where its permissions could be compromised.

Other than that, the visudo program works like the VI program — it’s a text editor, but you should familiarize yourself with the editor before messing with your sudoers file.

WARNING: You can lockout ALL users from your machine if your fat fingers or VI ignorance corrupt this file!!! If you are at all unsure of your VI abilities, please review our article: VI Overview.

The goal in editing this file is the addition of a single line of text:
your_poweruser_name ALL=(ALL) ALL

There are a lot of other custom modifications you can make to this file to allow certain users access to individual functions, but that’s a more advanced topic.

Save the file, but DO NOT CLOSE THIS WINDOW. If you made a mistake, you need access to this file in order to fix it. I recommend leaving this window open until you’ve got EVERYTHING locked down and you’ve verified that it works.

Again, go back to your desktop machine and test that you can still login using a password. Once you’re in, try using the sudo command and make sure that you an use it to execute commands.

Add Your Public Key to the Web Server

In a new window, login to your web server from your desktop machine. You should still be prompted for your password.

See if you’ve already got a .ssh directory in your user’s home directory:
[prompt]$ ls -Gal

If you don’t have it, create it:
[prompt]$ mkdir .ssh

Now, move into that directory:
[prompt]$ cd .ssh

If you don’t already have a file named authorized_keys, you need to create it (again, you can use the VI text editor)

You need to paste your entire public key from your desktop machine into this file on the web server. IT MUST FIT ON ONE LINE. SSH expects each key to occupy a single line.

*In VI, you can hit ESC then type :set nu to see line numbers.

Once you’ve pasted in your key, save the file and adjust the permissions:

[prompt]$ chmod 644 ~/.ssh/authorized_keys
[prompt]$ chmod 755 ~/.ssh

Remember:
1. Each public key occupies ONE LINE in the authorized_keys file.
2. The authorized_keys file must be read-only for the group and others: 644.
3. The .ssh directory can’t be group writable: 755

Disable Password Logins

The goal here is to disallow random hackers guessing at passwords by disabling password logins entirely. Logins will be verified via keys, and we change how SSH behaves by editing the /etc/ssh/sshd_config file.

Make the following edits to the /etc/ssh/sshd_confg file e.g. by typing sudo vi /etc/ssh/sshd_config

Uncomment the PasswordAuthentication line to
PasswordAuthentication no

And change the line for PermitRootLogin to:
PermitRootLogin no

Then reload the conf:
[prompt]$ sudo /etc/init.d/sshd condrestart

WARNING: KEEP THAT WINDOW OPEN. Open a new window, then try to login as your user once again. You shouldn’t be prompted for your password… you should be prompted for your passphrase — this is the passphrase you created when you created your key.

Try switching to the root account after logging in:
[prompt]$ su - root

And finally, attempt to login as the root user from your desktop. It should fail.

Summary

Congratulations! If you’ve gotten this far, you’ve taken some big steps in securing your server.

Once you’ve verified that all of this stuff works, you can close the login windows. If something did not work, LEAVE THOSE WINDOWS OPEN and call a friend — find someone who knows Linux system administration to help you out. This is even more important if you don’t have physical access to your server.

Links

Here’s an article I referenced while writing this:
http://www.webmasterworld.com/linux/3285421.htm

Enabling SEO Friendly URLs in MODx (part VI in the series)

Apache .htaccess Rewrites are Powerful
Apache .htaccess Rewrites are Powerful

Many content management systems rely on URL parameters like ?page=3 to determine which page is displayed to the user. MODx (like many other CMS’s) can use Apache’s .htaccess file to rewrite URLs so they are easier to read, e.g. www.mydomain.com/modx/tutorial, and this usually results in higher SEO scores. This article and its video walk you through how to accomplish this for MODx running on an Apache web server. Windows servers have something similar, they just charge more for it (haha).

Here’s the video. I was going to re-do this in high-def, but this was one of those lightning-strike rants that I was on… I just know it wouldn’t be as good if I attempted to remake it.

* I mispronounced MODx in the video (sorry). It should be “mod” as is “modular”.

The Quickie Text Version of the Video

  1. Make sure MODx is installed and your site works.
  2. Go to the root of your site, verify that you have an .htaccess file (MODx often includes a dummy file named “ht.access” which needs to be renamed before it is parsed). Be sure to keep a backup copy of the original!
  3. Edit the .htaccess file and type some junk at the very top of the file. For example, type in “asdpfasdfj” at the top of the file, then save it. Now try to visit any page on your site. You should get an server error, and this is GOOD! This means that the .htaccess file is being parsed, so go back and delete that junk from the file. If you don’t get an error, it means that the .htaccess file is NOT being parsed, and you may need to contact your ISP to see how to enable it. You can’t get friendly URLs working without this!
  4. Once you’ve confirmed that your .htaccess file is being parsed, you can make the appropriate edits (see below). The dummy file included with your MODx install is very well annotated. I’ve listed the most important bits below (please change yourdomain to the appropriate domain). Note that in some of the lines, you must precede periods with a backslash (i.e. you must escape them). Any line starting with “#” is a comment.
    # Vital components of your .htaccess file
    RewriteEngine On
    RewriteBase /

    # Force “www.yourdomain.com” instead of just “yourdomain.com”
    RewriteCond %{HTTP_HOST} .
    RewriteCond %{HTTP_HOST} !^www\.yourdomain\.com [NC]
    RewriteRule (.*) http://www.yourdomain.com/$1 [R=301,L]

    # The Friendly URLs part
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

  5. Make sure your site is still working… you can still use the same un-friendly URLs after making these edits; you just want to make sure you didn’t misspell something in your .htaccess file and cause it to parse incorrectly.
  6. Login to the MODx manager (www.yoursite.com/manager) and go to Tools→Configuration→Friendly URLs and change the following settings:
    * Use friendly URLs: YES
    * Use friendly aliases: YES
    * Use friendly alias path: YES

You should now be able to navigate to pages by using their alias!

More Information

Friendly URLs Guide — From the MODx Wiki.

Technical Details about .htaccess

What exactly is happening? Well, the .htaccess file can control a lot of server settings, and you can think of it almost like a style sheet: the server has global settings, but the .htaccess file provides a way to override some of those settings locally for a particular directory or site. It really merits its own article (stay tuned), but let’s look at the the friendly URLs part of the .htaccess file.

The core of this functionality is Apache’s mod_rewrite module. My snarky description is this: it lets the server lie to your address bar! Your browser window may SAY that you are visiting www.mydomain.com/modx/tutorial, but really, the page you are viewing (on a MODx site) is:
www.mydomain.com/index.php?q=modx/tutorial
Try this on your own MODx site! You should see the same page as you did when you visited the friendly URL.

Here’s what the .htaccess file is doing. The first RewriteCond is checking the file system for a file of the name you are requesting. In the example, it’d look for a file named “tutorial” in the “modx” directory. The “!-f” at the end of the line is basically saying “IF there isn’t a file of this name”… then the next line’s “!-d” says “OR there’s not a directory of this name”, THEN perform the rewrite defined by the RewriteRule.

Here you see a good example of a regular expression, and if you haven’t heard that term before, I can sum up quickly: if you’ve ever done a “search” or a “find and replace” in a document, you’ve utilized a simple type of regular expression. A regular expression searches for a pattern. The $1 is a common shorthand notation that back-references what exactly was found, in this case, it’s the argument that’s being passed to the server for the REQUEST_FILENAME, i.e. “modx/tutorial”. The contents of the $1 variable is then added onto “index.php?q=” and you end up with the REAL URL being:
www.mydomain.com/index.php?q=modx/tutorial

Tricky tricky! I skipped over a lot of details for this brief overview, but hopefully you can see some of the process here. This is how most CMS’s handle this sort of thing. The .htaccess parsing requires more overhead from Apache, but it offers a lot of flexibility in how you access your files, and for most sites, this is a very worthy tradeoff.

Creating Templates in MODx Part II (part V in the series)

Now that you are able to create basic MODx templates from watching the previous video, this video shows you how to extend their functionality even further with the inclusion of reusable chunks of code and dynamic PHP snippets.

A video used to be embedded here but the service that it was hosted on has shut down.

Vocabulary

You only have to learn a couple new terms to understand what MODx is talking about — it’s not a steep learning curve, so jump in!

  1. Chunk — any bit of reusable text (usually HTML). Text used in a site’s footer is commonly placed into a chunk. MODx references chunks using double curly-braces: {{name_of_your_chunk}}, and they can be used almost anywhere, including page content and templates. Chunks can also contain Snippets!
  2. Snippet— this is a bit of PHP code (I remember Snippet by its double-P’s: sni-PhP-et). You can literally cut and paste almost any working PHP script into a MODx Snippet; once it has been created, you reference it using either double-square brackets or with a bracket and an exclamation point: [[Like_this]] or [!Like_this!], depending on whether you want it to always execute, or whether its output can be cached. See the MODx Wiki for more information.

Clarification

To clarify the process here, first you create a Chunk or a Snippet by logging into the MODx Manager and navigating to Resources→Manage Resources, then selecting the appropriate tab (for Snippet or for Chunk). You paste in the code you want to use, then save it. Back in your documents or templates, you can reference the Chunks and Snippets by name, flagging the names with either “{{ name }}” (for Chunks) or “[[ name ]]” (for Snippets). When MODx parses the document or template, the text in the Chunk will replace the tag, or in the case of a Snippet, the code will execute and its output will replace the tag.

Template Tips

  1. If you keep pasting the same bit of text into lots and lots of pages, consider adding that text into a Chunk. Also consider adding the reference to that chunk to your template.
  2. Set up a good working Snippet to auto-generate your menus. Wayfinder is a very flexible Snippet designed explicitly for this task, and it is included with MODx. Check the official site for up-to-date documentation; there are also lots of examples on the MODx Wiki
  3. Plan your site and its templates before trying to code them; then make sure you code them before adding them to MODx.
  4. If your site has too many templates, you probably are doing something inefficiently. Ask around: is there a better way to accomplish what you’re trying to do?
  5. When adding your templates and its associated chunks/snippets to MODx, take advantage of the “category” field. It offers a simple way to keep your components organized.

Other Tutorials: don’t just take our word for it

  1. Net tuts
  2. Bob’s Guides — Bob is very active in the MODx Forums, and he knows what he’s talking about.
  3. The Coding Pad

Download MODx Templates

You can also download MODx templates from a number of other sites! And since it’s so easy to integrate existing templates, you can download templates for virtually any platform and incorporate them into MODx.

Summary

After watching these two videos, I hope you can see how simple it is to get CMS functionality out of existing HTML/CSS using MODx. Again, the big thing I didn’t explicitly point out in the videos is that MODx stores its template code in its database: you can create and use a MODx template without uploading a single file to your webserver. Of course, if you want to reference CSS or Javascript files on your webserver, it’s accomplished in exactly the same way as you would do it on a static site: just make sure your paths to your resources are correct. I’ll cover how to write your own Snippets in another video. For now, just review the wiki page about MODx placeholders as you build your own templates. Please note, I did make one slip up in the video… Snippet values should usually include backticks, like this: [[MySnippet? &parameter1=`value`]].