Author Archives: lkeyes70

WordPress Woes and .htaccess

After spending months working on our new WordPress site hosted at Linode, we were ready to flip the DNS from xxx.xxx.xxx.xxx to a realdomainname.org.

Not so fast!” said the SEO expert… “you need to have your 301s in place.” So, we went through the drill and identified the top 100 pages on the old site. These were pages that had been visited in the previous month or so, and also ones that we knew were especially popular. We then created an .htaccess file, which is a file containing instructions for any visitor who arrives at the new site via a search on an old URL from the old site.   Here’s a snippet of what it looks like to start.

# LK 5/2/2016 
Options +FollowSymLinks
RewriteEngine on
Redirect 301 /node/96821 http://www.realdomainname.org/toolbox/
Redirect 301 /node/120 http://www.realdomainname.org/designing/
Redirect 301 /node/2 http://www.realdomainname.org/
Redirect 301 /node/11522 http://www.realdomainname.org/basics/
Redirect 301 /node/13152 http://www.realdomainname.org/toolbox/
Redirect 301 /node/12931 http://www.realdomainname.org/activities/

So far so good. Except this is ass-backwards. We should have worked out the WordPress URLs before creating the .htaccess file because WordPress itself has something to say about the contents of the .htaccess file, viz:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

These entries in the WordPress file are created based on a WordPress setting under Settings->Permalinks which allow you to change what shows as a URL for access. You can choose among a number of options including having the blog post title in the URL as well as the post’s category. (another reason for assigning a post to only one category).

One you have saved the permalinks setting, WordPress will write to your .htaccess file. If this is the first time, you will see that the .htaccess file contains lines similar to those in the # BEGIN WordPress block above.  Otherwise, my guess is that WordPress rewrites the block to accommodate how you want the permalinks to appear.

Other issues:

Note the lines

<IfModule mod_rewrite.c>
RewriteEngine On

refer to an Apache web site module called mod_rewrite. This is a piece of code in the the Apache web server which accomodates the rewriting of URLS.  So, for example, maybe you have a post that is physically located at:

 /var/www/html/wordpress/wp-content/posts/mylovelypost.html

A default URL for a blog post might look something like:

http://www.realdomainname.com/index.php/wp-content/mylovelypost/

However, after implementing your pretty permalinks it will automatically reset itself to

http://www.realdomainname.com/mylovelypsost/

or even

http://www.realdomainname.com/mylovelycategory-mylovelypost/

if you choose to include a category.in the URL formula. This “virtual” URL is the one that gets indexed by the search engines, and so is worth giving some serious thought so that you get it right the first time.

Note that this whole exercise is possible only on self-hosted WordPress sites, not on sites hosted at WordPress.com. So, at this writing, the techfornoprofits.com  site is hosted at WordPress.com, and so URLs are fixed using the formula of http://site+year+month+day+blog_post_title.

https://techfornonprofits.com/2016/04/12/ten-ways-to-improve-a-grant-application/

So, having gotten the permalinks thing squared away, I then added the 301 redirects to the .htaccess file.  These are in the  format of:

Redirect 301 /node/96821 http://www.realdomainname.org/toolbox/

Statement = Redirect 301
Old site page name
New site address.

The /node/96821 address for the old site page is a convention from Drupal. (Drupal is another content management system. Our new WordPress site is  a conversion from a Drupal 6.7 site).

Two notes regarding the .htaccess file:

  1. The .htaccess file is normally a hidden file, so it isn’t visible within a normal directory listing. There is a setting in FileZilla which permanently “show hidden files”  If the file name is prefixed with a period, it is considered a “hidden” file.
    .
  2. Once the .htaccess file has been created the best practice is to turn off the ability for it to be written to by changing the file permissions. Conversely, if you either don’t see any changes or get an error message when attempting to adjust the Settings-Permalinks in WordPress….the .htaccess may either be non-existent, or flagged as read-only. WordPress has to be able to write changes to the .htaccess file.

At this point the permalinks are squared away, and the 301 redirects are in place. But our woes are just beginning!

Nonprofit CRM Overview

NonProfitCRMIn designing our non-profit CRM, we have been looking at all of the functions that we’d like to track.  At a minimum, we think each of the entities above will use one database table. In practice each entity will have an associated “interaction” table and “look-up” tables that feed picklists of options.

A little background. Our organization makes grants to schools and community groups. Many of these grants are funded through commercial sponsors, or through philanthropic individuals or organizations. Thus we have both Grant Prospecting and Grant Application Management functions.

Grant Prospecting — This is us prospecting and managing the workflow involved in applying for a grant. Recently when it gets  down to the application process itself  we have we have worked in Slack.

Grant Application Management — As we receive grant applications we have to process them and eventually evaluate them. We currently use LimeSurvey for our online grant application.

Sponsor Prospecting — If we don’t have an individual or foundation donor, we may fund a program through a sponsor; a company that wants to promote their community engagement or charitable contributions.

Contact Management — The contact table part of our design includes all the usual information about contacting a person In our database design, this may actually turn out to be  a hidden many to many table. One of the objectives that I want to address is the ability to look at a single person’s contact information and determine what our relationship(s) are with that person. A person could be a donor, a member, a volunteer, a member of our board, member of our advisory board. and our lawyer. This is really what CRM is all about, as well as the ability to track the relationship steps with the person at any stage of the relationship.

Membership (Donor) Management. We used to do this in Little Green Light. We’re not sure our business model going forward lends itself to membership.. but if it does, this is where we’d like to track members.

Media / Outreach Lists — We have 3782 media contacts to which we send press releases etc.

Admin — Could we provide forms for our usual HR functions like time sheets, vacation accrual, expense reimbursement, travel schedules, etc?

Note that this design exercise is independent of any particular kind of software. We have bits of data scattered in spreadsheets, word-processing files, online applications such as LimeSurvey and Little Green Light, FileMaker databases and of course eMail.

Update: I’ve added two additional tables; one for “contacts” (which will feed its contact and address data to the other tables), and  “projects” table which contains data about each project.

 

 

 

Ten Ways to Improve A Grant Application

Odds and Sods

Random Tips

  • Panic in the ranks! This is not the first thing you want your users to see in the morning as they attempt to log into to complete a grant application:
    The table "{{settings_global}}" for active record 
    class "SettingGlobal" cannot be found in the database."

    After some poking around it turns out we were out of allocated disk space on the Linode.  df -m showed 100%. I think this was related to a backup and restore that I had done a day earlier; which preserved the old image as it copied a new version  to the same allocated disk space. The actual error was returned by LimeSurvey, which was reacting to a system 8 error generated by mySQL.

  • Trying to see the analytics for a bit.ly link?  Just append a plus sign ‘+’ to the link. This will show the statistics for the link instead of what the link points to.

Stuff I’d Like to Try Out

Two “glue” programs that process something in one program, based on a trigger that is set in another program.

Two forms program that make web forms.

Links of Interest

50 tools for project management. (from Zapier)

SalesForce: Donors and Donations

Looking into this further,  the SalesForce non-profit starter pack deals with Donors and Donations.

A typical issue when dealing with donors is that you often want to track relationships between different donors; for example spouses in the same household who contribute independently to your organization. One way of doing this (not just in SalesForce) is the notion of a household.  In database terms, a household would represent many-to-one relationship where a one or more contacts are members of a single household.

SalesForce will accommodate no less than 4 different kinds of contact/account models. The details are explained in their FAQ about account models.  The upshot is that out of the box, the most recent version of their non-profit starter pack uses what they call their household model.

SalesForcehohousehold

If you check out the terminology in the diagram above, you can see that they are mapping non-profit terminology to their sales terminology.

Non-Profit SalesForce
Donor Contact
Household Account
Donation Opportunity

We’ll have to look at this when it is wired up as a online form.

SalesForce NonProfit Starter Pack

We’ve been looking into a Customer Relationship Management system for our nonprofit, that will encompass more than the just the usual fundraising type of database. One option that we’re taking a hard look at is the cloud-based SalesForce nonprofit version. One of the tasks is to learn the workflow jargon such as:

  • Opportunity Stages
  • Opportunity Sales Processes
  • Opportunity Record Types

Salesforce provides a donation for up to 10 users for any qualifying non-profit organization. The Nonprofit Starter Pack is a pre-configured set of functions and data elements that can be overlaid on to a “standard” SalesForce company installation. The donation includes significant online support, documentation,  and forums with members from nonprofits who are using the system.

As a preliminary exercise, I’m going to attempt to import our donor data from our previous Little Green Light system. This consists of two tables; a donor contact table and a transaction table which lists all of the donations made by members in the donor table. Both of these are currently living in FileMaker which can export into a variety of file formats including Excel and comma delimited (text) files.

WordPress: Fix the File Upload Size Limit

On our WordPress site we want to allow the site manager the ability to upload PDF files which can then be downloaded by our blog viewers. While working out this process we ran into a problem with the file size; any file larger than 2 megabytes was not allowed to be uploaded to the site.

Rather than having this setting located somewhere within WordPress, it turns out that the setting is set by the PHP installation.  (PHP is the language that WordPress is written in, and WordPress the application is written as a series of PHP files).

As I was working through this issue, the first embarrassment was that I couldn’t even find the WordPress installation on my Linux server. Usually WordPress is supposed to be installed somewhere relatively transparent, like the /var/html/wordpress folder. Instead mine was buried under  /srv/www/li999-999.members.linode.com/public_html; somehow related to my virtual host from Linode

As my plumber says, when looking at the latest plumbing problem in our basement, “I wonder why they did that?”  Whatever. The way I finally found this out was to search for the one file that is in every WordPress site; wp-config.php.  I did this by firing up the FileZilla FTP program, and doing a search for remote files.

SearchRemoe

Having found the root directory of my WP installation,  I now needed to find the location of the PHP configuration file. I used a similar search in FileZilla and came up with two php.ini files.  Which was the “real” one?

Actually, I didn’t need to do that. Instead, I needed to get to have a script that calls the phpinfo() function which displays a nice list of all the php configuration parameters. Placed in the root directory of my web server, and then called from a web browser, this script displays all of the inner workings of the php configuration of my site.  Here’s the script:

<?php
// Show all information, defaults to INFO_ALL
phpinfo();

?>

This script is saved as GetPHPInfo.php and copied back to the root directory of the web server.

http://mywebsite/GetPHPInfo.php

Call this script in the web browser and it produces  the following:

PHP1

The above is just the tip of the iceberg. Scrolling waaaay down, I find the following parameter in the “core” section of the page:

php2

That is the size restriction, and it is this parameter that I need to change.  I’m thinking that 12 megs should be plenty.  Looking back up top in the 6th line, I see the “Loaded Configuration File” is located at:  /etc/php5/apache2/php.ini  This is the file I’m going to change. So, its back to FileZilla to find it, download it and edit it in Notepad++

PHPini

I downloaded the wp-config.php file to my local machine using FileZilla.  Then I edited the file using Notepad++. to change the  2M to 12M.  Then I uploaded the file via FileZilla back to the web server.

At this point I needed to reboot the web server, Apache2. Depending on the your installation, there are a couple ways to do this at the command line:

$ sudo /etc/init.d/apache2 restart

Or,  in the case of the lazy systems administrator, I just rebooted the whole server. This takes less than two minutes.

The result is now we can upload files that are a maximum of 12 megabytes in size.

I get to do this on another WordPress server too.  Oh joy!

Slack for Grant Applications

We have just put Slack through its paces as a collaboration platform for applying for a couple of grants. We had a distributed team of three core team members:

  • The brain (BR) (who wrote most of the narrative parts of the application)
  • The numbers guy (NG) (who vetted the budget documents and provided updated balance sheet and income statements)
  • The grant slave. (GS)  (who managed the online submission process)

Like all grant applications these days, the application is online. The grantor uses Foundant as their online platform, which provides  a pretty good interface for the applicant.

The Toolbox

PDF Wranglers

Text-based attachments are usually PDF files, so you need some way to create these and combine them. Native Macintosh apps like Numbers can create PDFs. It also turns out that you can combine PDFs using the Mac Preview program. You can’t do this with the free Adobe Reader which I found out to my chagrin, loosing an hour or so in the process of trying.

DropBox

Since we were working from home and from the office,  with both Windows and Macs, we needed a common place to store source files that we were adding to the online application.

Text Editor

OmmWriter on Windows and is now available for the Mac and iPad.  (I used the Mac text utility.) OmmWriter can export directly to PDF if needed, but usually I’d copy and paste directly into the online application. OmmWrite provides a critical function…it counts both words and characters so that you can stay within those restrictions if they exist. In our applications they did…and I spent considerable time editing the Other People’s stuff. Death to adverbs!

Spreadsheet Program

Numbers on the Mac,  Excel on Mac or Windows. Both create PDFs.

How we set up Slack

Each contributor is set up as a member of our Slack Team, so it is possible to send direct messages between each other.

We have a single Slack channel called #fundraising where we place all of the items that we have under discussion. If I had to do this again, with simultaneous applications, I might consider creating one channel for each grant application, however we shared a lot of data between the two applications as they were from the same funder.

The core team members are members of #fundraising. The rest of our non-profit board are also members but weren’t active during the creation process.  Obviously,  anything published in #fundraising is “public” or open for inspection to the team and the members.

The Work Flow

Grant Slave (GS) establishes account with the funder’s system, and downloads a PDF of the blank application.

GS posts the blank application to Slack in #fundraising.

Discussion within #fundraising, about who takes what for the writing.

As BR and NG prepare their text files,  GS starts filling in the online application with the routine stuff; name and address of the our organization, our mission,  etc. .

As the application becomes filled in, it gets printed to PDF and the PDF is posted in the #fundraising channel.

Team members view the PDF from within Slack and make suggestions for changes. They also post their new text in the channel. This is easiest if it is posted as a simple Slack message, as opposed to a Slack snippet or Slack post.

GS enters updated text in the online application,  usually by copying and pasting text that the others have provided in #fundraising.

Iterate.  As each new version of the application PDF  is generated, it gets posted to #fundraising and the earlier versions are deleted.  The idea here is that people are always looking at the most recent version of the application PDF.

Discussion

Note a couple things:

  • Only one person touches the online application.
  • Everyone works with and edits the most recent version of the application. This is effectively a version-control system.
  • This system allows creative people (BR and NG) to be creative, without having to worry too much about the mechanics.

 

 

 

SEO, Oh No!

stupid-487043_640

I’m always amazed at stupid I was yesterday*. We’re creating our brand spanking new web site for our non-profit, and my attitude to SEO (or Search Engine Optimization) was….”we’ll since we haven’t put up the web site we don’t have any statistics, and since we don’t have any statistics, there is no point in doing SEO until the site is up.”

WRONG.

In fact, I should have done this with my own blog site as well,  recently switched from Blogger to WordPress. So that is two strikes.

It began innocently enough… literally with a water-cooler conversation with an SEO expert, who made the following points:

  1. Run Google Analytics on your old site. Identify the top pages that are always accessed. These are the pages that you want to transfer to your new site; as intact as possible, even to using the same folder structure as the old site.
  2. Can’t run Google Analytics on the old site?  Its probably because GA was set up with a personal Google account from someone long gone from your organization. So, next time…do the organization a favor and use a generic account,  like webmaster@myorgname.org so that someone else can access Analytics if you get hit by a bus. And there should be a next time….like right now.
  3. Even if you are unable to see statistics from Google, you can run an Alexa search which searches links in and out of your site. Lots better than nothing. Or if the old site is a Blogger or WordPress site, you can get statistics from those hosts.
  4. Assuming that you can identify popular pages, you want to flag the pages on the old site with a redirect from the old page to the new page. If correctly redirected, the page rank and statistics from the old site will be transferred to the new site. Do this for enough pages and you’ll preserve the old site page rank going forward.

Notes: * from Alan Weiss,  ” I’ve been fond of stating the following truth for years: I’m constantly surprised at how stupid I was two weeks ago.”

Apple Downsizes. New iPad Pro and iPhone

Screenshot_032116_020923_PM

Apple is holding its March announcement, and it is an odd mixture of a sort of fashion runway theme, snake oil salesmanship, and religious revival. It was a bit disconcerting to see CEO Tim Cook slavering over the new colors for the watch bands for the iWatch. The whole presentation seemed to have a sense of desperation.

Incredible!, Awesome!, Epic!, Incredibly!, Biggest!, Unbelievably Thin! I keep thinking there should be a way to lend a greater aura of dignity to the whole proceeding, but always end up feeling a little queasy.

They are even claiming that  your iPhone will help you sleep better.

Two interesting segments of the presentation revolved around a new iPad and health-related software.

  1. The Health App is a dashboard for health data which consolidates health data from other sites and devices. There was discussion of ResearchKit, which uses the iPhone as a data collection device for research data, and a new framework called CareKit, which delivers.
  2. iPad. A new iPad Pro with a 9.7 inch display. They are saying they are targeting Windows users. There are over 600 million PCs in use today that are over 5 years old.  The iPad solves problems that you never knew you had. There is an available smart keyboard, and the Apple Pencil. The cameras have been upgraded to a 12 megapixels, and the ability to shoot 4K video. The front camera is 5 megapixels. Starting at $599 at 32GB, If you add an Apple Pencil, and a smart keyboard, the cost will approach a thousand bucks.

Outside of these two announcements there was the aforementioned discussion of new fabrics, styles and colors for the Apple Watchband, an upgrade to Apple TV, and upgrades to a few of the apps on IOS 9, including the lame Notes and News apps, and a new smaller iPhone. All this is accompanied by polite applause and accompanying whoops.