Tech

Build your own FAQ in Drupal

Submitted by tomo on October 13, 2012 - 12:15pm

Websites, including Drupal sites, often need Frequently Asked Questions and answers to them. Drupal, as a content management system, should manage your question and answer content intelligently. With all the great modules contributed to Drupal's community you might think there are some good FAQ modules. In my experience, the Drupal FAQ module is too rigid, and therefore unusable for most of my sites. But we can build a FAQ system using basic Drupal building blocks.

What we need: taxonomy, blocks, views, a few lines of PHP (that can be stored in the database - no custom module required)

1. Content type: Create a new content type. CCK is optional here, as you can just use Title as Question and Body as Answer.

2. Vocabulary: Create a new vocabulary called FAQ. Add a few terms if only for testing.

3. Devel Generate: Optional - requires Devel module's devel_generate to generate some test nodes with test questions, answers, and topics. devel_generate can be run from the command line too if you have drush installed - just run "drush genc". Anyways, generate a few dozen nodes, as many nodes as questions you have. It'll be easier to mass edit the questions once the nodes have already been generated.

4. Views: You'll need two views although they can also be two displays of a single view, so let's do that.

a. Create a view, filtered by your FAQ content type (and published or published/admin).

You will add three node fields:
Node: Nid (Nid) [make this field hidden, but its value is used in the rewritten Question field below]
Node: Title (Question)
Node: Body (Answer)

For the Question, rewrite the output to:

<a name="q-[nid]"></a>
[title]

You'll have on argument, which is the Term (FAQ vocabulary topic) in the URL.

- Configure Argument Taxonomy: Term
-- Provide default argument
--- Default argument type: Taxonomy Term ID from URL
-- Validator: (Choose your FAQ vocabulary)
-- Argument type: Term name or synonym
-- (Optional) Transform spaces to dashes in URL

Now turn this default view into a page that's not overridden in any way. Set the URL to be something that's NOT your vocabulary name because your URL will conflict with the default taxonomy paths ("taxonomy/term/%" - which Taxonomy sets up path aliases for from each vocabulary with each term - but that page may also be being overridden by a view included by Views by default). So if you want your URLs to be like "/faq/return-policy" then name your Vocabulary like "FAQ Terms" instead of "FAQ".

At this point you should save your new view and be able to go to "/faq/troubleshooting" or whatever. It will give you a list of questions with answers. But usually a FAQ section will also list out all questions at the top with links to answers below. How can we accomplish that?

b. Let's create a new Display that's a Block. Now override the fields and remove the Answer field. Override the display of the Question to:

<a href="#q-[nid]">[title]</a>

Optionally, set a blank title for this field. Then we will have a block that is just a list of questions. But the argument won't work anymore since it's a block. So you need to override the argument "Taxonomy: Term".

- Default argument type:
-- PHP Code
--- return arg(1);

- Validator: Basic validation + Transform dashes in URL to spaces in term name arguments

This will find the term "charity" in the path "/faq/charity" and pass it on.

5. Now that the block is created, you need to make it display. We want to display it on the top of our first view!

This is assuming you have a region in your theme for blocks at the top of content in pages. You could choose another location but it should really appear as the first content you see. But you want this block to appear ONLY on this page! So in block admin, configure the block you just created, and under:

Page specific visibility settings
- Show block on specific pages:
-- [check] Show on only the listed pages.
Pages:
- Type in "faq/*"

Save the block. Now your question list with links to answers further down the page should be appearing at the top of your FAQ pages!

7. Next, you need a list of your categories. Sadly, there's no easy way for Drupal to do this. Views has a view type for taxonomies which is unfortunately not very powerful and so we can't use it to get links to "/faq/[term]" as it doesn't allow us to rewrite our own links. It allows you to link to term pages but those pages are rendered by either the Taxonomy module or that default view I mentioned earlier. Trying to override those paths with our own view is a mess, probably due to weighting.

Anyways, we can easily create a list of topics with links with a tiny bit of PHP. Create a new block using the Block admin page. In the block body:

<?php
$tree = taxonomy_get_tree($vocabulary_id=YOUR_FAQ_VOCABULARY_ID_HERE);
$html = '<ul>';
if ($tree) {
    foreach ($tree as $term) 
        $html .= '<li>' . l($term->name, 'faq/' . str_replace(' ', '-', mb_strtolower($term->name))) . '</li>';
}
$html .= '</ul>';
return $html;
?>

Again, set this block to only appear on "faq/*" pages. Then configure its location into a sidebar or somewhere and you will be displaying links to each of your FAQ topics and you're done!

Speeding up your slow Android smart phone

Submitted by tomo on October 12, 2012 - 8:10pm

Some time after getting a new phone or after wiping and reinstalling the phone's OS (or upgrading to a new version of Android), the phone starts to bog down and feel laggy compared to before. The hardware is the same (well, maybe the phone's battery has lost some charging capacity but the memory and CPU are still as good as when they were manufactured), so it must be something software-related, right? I mean, this problem happens with Windows PCs too (but not with Linux/OpenBSD...).

Not the thousands of stored SMSs and phone call logs

At first, I thought it might be the thousands of SMSs (and hundreds of phone calls) stored on my phone, which I keep for convenience. On my old Symbian OS Nokia these SMSs would really slow the phone down and so I would have to delete messages every month. But there's no good reason a modern phone can't handle nearly unlimited messages as easily as just a handful. But I gave it a shot, deleting all SMSs (first backing the messages and call logs with SMS Backup & Restore app) and phone calls, but it had no effect.

Not task killers

So then I wondered what mobile apps might be slowing the phone down. There are various task killer apps in the app marketplace and they will help you free up memory. I kinda of wanted to see a more granular view of what resources the various apps were using, like Task Manager or Activity Monitor. So I opened up Terminal Emulator and ran 'top' which doesn't redraw the screen like it would in other terminals, but simply writes out all processes to the screen again on each refresh. So it's slightly harder to understand.

Using an automated task killer is controversial. It's possible that using an automated task killer will confuse Android's memory manager.

Not the version of Android

Upgrading Android. Right after you load a fresh ROM onto your phone it is probably going to be as fast and responsive as it ever will be. Then some months down the line it's running slowly.

Remove widgets, V6 Supercharger your memory mangement, and turn off GPS

Here are the things that do help speed up your Android phone.

1) Remove some widgets and live wallpapers.

2) Advanced users: V6 Supercharger Script

3) In the end I think turning off GPS helped the most. This is likely due to location apps polling your location nearly constantly when it's on.

Mass editing nodes in Drupal can be a chore. If you just want to edit some attribute and set it to a single value for many different nodes then Views Bulk Operations can help. But you may instead want to make some quick changes to the titles, bodies, and CCK fields of a bunch of nodes of a certain type. The default way would be to open each node in a browser tab, go to their edit forms, and then operate on each one individually. Can we come up with a better way?

Multi Node Edit is a module that sounds like it could help. It promises to give you a page with many node edit forms. Unfortunately, this is not the case. By itself, this module is not usable to users. If you write some code to use it like a library you might be able to create a page with many node edit forms on it.

Recommendation: This module isn't useful to most people. It might be useful if you're writing code for a custom page.

Editview (editview) is the easiest to use, you just build Views and select 'Style' of 'Editview' in one of your displays. It works on the whole display, so all fields become editable. Unfortunately, you can't control this. Some fields shouldn't be editable, and so sometimes they just don't appear at all. Other times you may want to view a field but not edit it. Unfortunately, this isn't possible, even when using Global fields. [This issue is tracked here: http://drupal.org/node/635076]

* In my case, I just wanted to get a link to edit the node. I accomplished this by adding a Node: Path field which shows the path/alias editing form.

Recommendation: Use Editview if you're comfortable with building Views. Then you can construct a view of the fields you want to edit, and make it easy to filter the nodes you want to edit.

Editable Fields (editablefields) - 6.2 doesn't integrate with Views, despite the README. 6.3 does integrate but not the way explained in the README.txt. There is no added View type to choose when creating views. The exported content types used for demonstration don't import either. Most fields aren't editable, but if they are there will be a new checkbox for editable with some options. However, the 6.3 version of the module is still quite buggy so it doesn't work at all.

Recommendation: Avoid Editablefields module for now unless you want to just edit fields in the node display.

Drupal Links in Content

Submitted by tomo on October 11, 2012 - 3:01am

Problem: In your blog posts you have a lot of links to other pages on your site, then one day you decide to change the URL pattern for all nodes on your site, or you change the pattern and slowly update paths to nodes by editing and saving them. Unfortunately, you had hard-coded paths in your content bodies and now they are all leading to 404 pages. What to do?

1) Link checker (linkchecker) module will find the broken links. This is something you may need to use.

2) Path Finder is a module that turns your node links into permalinks with node id (slug) at the front of the URL so that any future change to title which results in a different URL still leads to the same node via the node id. Example: http://www.example.com/837/latest-news/my-descriptive-seo-friendly-url

Of course, this doesn't help you once you already have a bunch of nodes and content linking to them, but it's one strategy to start with. Then if you do change the titles or patterns of your nodes, as long as the node id / slug is still at the beginning of the url, then you won't get any 404 errors, although you'll then have multiple URLs pointing to the same content. So this isn't ideal.

3) Turn on Pathologic: "Pathologic is an input filter which can correct paths in links and images in your Drupal content in situations which would otherwise cause them to “break;” for example, if the URL of the site changes, or the content was moved to a different server. Pathologic is designed to be a simple, set-it-and-forget-it utility. You don't need to enter any special “tags,” path prefixes, or other non-content noise into your content to trigger Pathologic to work; it finds paths it can manage in your content automatically."

4) If you just need to remove a base path (like http://www.domain.com:8080) from all URLs, then URL Replace Filter (url_replace_filter) will suffice.

5) If you need to do more complicated search and replace on URLs, and want to use regular expressions, then use Search and Replace Scanner (scanner).

Finally, use Global Redirect to always have a single canonical path for each piece of content.

Dealing with Spam Comments on a Drupal Site

Submitted by tomo on October 11, 2012 - 1:26am

Drupal sites, like any content sites, naturally receive a lot of spam comments. Any blog or blog-like site which allows unauthenticated or anonymous users to comment on posts or any content is open to spam because spammers just want to have links to their websites displayed by your website for link-building purposes which is important for SEO. Spam comments used to be much more obvious as in blatant ads for penis-enhancing drugs. Nowadays, spammers are using more sophisticated scripts that are still easy to detect - by humans and usually also by spam-detection software. New spam might praise your blog or quote something you said in your blog post or just say something generic, perhaps on a related topic or perhaps not related at all. Then they will have their spam website in the URL field, if not also in the comment text. If the website has keywords which are totally unrelated to your blog, you can bet it's spam.

What can a Drupal website do about spam?

One old solution for spam, a common plugin on WordPress sites, is called Akismet. Akismet is a service and requires you to create an account and get an API key from them. Then they will help you detect spam.

Drupal has something like Akismet but improved and it was created by the Drupal creator himself. It's called Mollom, and it's also a cloud-based service, and you also create an account with them. Mollom is free to use although there are some paid services. I use Mollom on this blog. It catches hundreds of spam comments for me but also lets in a single false negative per day or so. I wouldn't have been able to turn on comments without turning on Mollom as I would immediately be deluged with spam. But I hope that Mollom continues to improve so that I don't even get 1 spam on most days.

Since I still do get some ham and spam comments, I have to process them somehow and report the spams to Mollom so they can improve their algorithms and heuristics for the future. Unfortunately, Drupal's default comments management view doesn't easily let me see if a comment is spam or not. In order to make that decision I need to see the URL and comment text that was saved. If there was no URL, it usually isn't spam, and if there was no URL in the comment text then most certainly it isn't spam. But if there was a link in the text, I need to see what site it links to, and see if the comment is at all intelligent or relevant. You can also tell by looking at any link saved in the URL field. Since Drupal's comment management page doesn't do this, I created a view, which you can import (this is Drupal 6) below.

The thing that Drupal's comment admin page offers is bulk operations. Mollom provides some operations such as report spam to Mollom and delete. This is usually what I want to do. Unfortunately, there's no way to use Mollom's actions in Views with Views Bulk Operations! So until this issue gets resolved (http://drupal.org/node/655846) I've done the next best thing which is to have links to the Mollom management page for each comment. It will still require you to open that page, select the reporting action you want, and then submit the form though. But this workflow has at least saved me some time and now I have removed all the really spammy spam from this site.

$view = new view;
$view->name = 'comments_more';
$view->description = '';
$view->tag = '';
$view->view_php = '';
$view->base_table = 'comments';
$view->is_cacheable = FALSE;
$view->api_version = 2;
$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
$handler = $view->new_display('default', 'Defaults', 'default');
$handler->override_option('fields', array(
  'name' => array(
    'label' => 'Author',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'link_to_user' => 1,
    'exclude' => 0,
    'id' => 'name',
    'table' => 'comments',
    'field' => 'name',
    'relationship' => 'none',
  ),
  'homepage' => array(
    'label' => 'Author\'s website',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'display_as_link' => 1,
    'exclude' => 0,
    'id' => 'homepage',
    'table' => 'comments',
    'field' => 'homepage',
    'relationship' => 'none',
  ),
  'comment' => array(
    'label' => 'Body',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'exclude' => 0,
    'id' => 'comment',
    'table' => 'comments',
    'field' => 'comment',
    'relationship' => 'none',
  ),
  'delete_comment' => array(
    'label' => 'Delete link',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'text' => '',
    'exclude' => 0,
    'id' => 'delete_comment',
    'table' => 'comments',
    'field' => 'delete_comment',
    'relationship' => 'none',
  ),
  'edit_comment' => array(
    'label' => 'Edit link',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'text' => '',
    'exclude' => 0,
    'id' => 'edit_comment',
    'table' => 'comments',
    'field' => 'edit_comment',
    'relationship' => 'none',
  ),
  'hostname' => array(
    'label' => 'Hostname',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'exclude' => 0,
    'id' => 'hostname',
    'table' => 'comments',
    'field' => 'hostname',
    'relationship' => 'none',
  ),
  'status' => array(
    'label' => 'In moderation',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'type' => 'yes-no',
    'not' => 0,
    'exclude' => 0,
    'id' => 'status',
    'table' => 'comments',
    'field' => 'status',
    'relationship' => 'none',
  ),
  'timestamp' => array(
    'label' => 'Post date',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'date_format' => 'small',
    'custom_date_format' => '',
    'exclude' => 0,
    'id' => 'timestamp',
    'table' => 'comments',
    'field' => 'timestamp',
    'relationship' => 'none',
  ),
  'view_comment' => array(
    'label' => 'View link',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'text' => '',
    'exclude' => 0,
    'id' => 'view_comment',
    'table' => 'comments',
    'field' => 'view_comment',
    'relationship' => 'none',
  ),
  'cid' => array(
    'label' => 'Mollom',
    'alter' => array(
      'alter_text' => 1,
      'text' => '<a href="/mollom/report/comment/[cid]">Report to Mollom</a>',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'link_to_comment' => 0,
    'exclude' => 0,
    'id' => 'cid',
    'table' => 'comments',
    'field' => 'cid',
    'override' => array(
      'button' => 'Override',
    ),
    'relationship' => 'none',
  ),
));
$handler->override_option('access', array(
  'type' => 'none',
));
$handler->override_option('cache', array(
  'type' => 'none',
));
$handler->override_option('css_class', 'view-comments-more');
$handler->override_option('header', '<style>
.view-comments-more table {
background: white;
position: relative;
z-index: 100;
}
</style>');
$handler->override_option('header_format', '2');
$handler->override_option('header_empty', 0);
$handler->override_option('items_per_page', 30);
$handler->override_option('use_pager', '1');
$handler->override_option('style_plugin', 'table');
$handler->override_option('style_options', array(
  'grouping' => '',
  'override' => 1,
  'sticky' => 0,
  'order' => 'desc',
  'columns' => array(
    'name' => 'name',
    'homepage' => 'homepage',
    'comment' => 'comment',
    'delete_comment' => 'delete_comment',
    'edit_comment' => 'edit_comment',
    'hostname' => 'hostname',
    'status' => 'status',
    'timestamp' => 'timestamp',
    'view_comment' => 'view_comment',
  ),
  'info' => array(
    'name' => array(
      'sortable' => 1,
      'separator' => '',
    ),
    'homepage' => array(
      'sortable' => 1,
      'separator' => '',
    ),
    'comment' => array(
      'separator' => '',
    ),
    'delete_comment' => array(
      'separator' => '',
    ),
    'edit_comment' => array(
      'separator' => '',
    ),
    'hostname' => array(
      'sortable' => 0,
      'separator' => '',
    ),
    'status' => array(
      'sortable' => 0,
      'separator' => '',
    ),
    'timestamp' => array(
      'sortable' => 1,
      'separator' => '',
    ),
    'view_comment' => array(
      'separator' => '',
    ),
  ),
  'default' => 'timestamp',
));
$handler = $view->new_display('page', 'Page', 'page_1');
$handler->override_option('path', 'views/comments_more');
$handler->override_option('menu', array(
  'type' => 'none',
  'title' => '',
  'description' => '',
  'weight' => 0,
  'name' => 'navigation',
));
$handler->override_option('tab_options', array(
  'type' => 'none',
  'title' => '',
  'description' => '',
  'weight' => 0,
  'name' => 'navigation',
));

Drupal has many SEO features built in and available as contributed modules. One main one being Clean URLs. But it's often said that Drupal gives you "just enough rope to hang yourself".

Drupal has a powerful module called Pathauto that lets you create powerful URL patterns based on Tokens. Any number of modules can provides tokens via the Token API for you to use to construct URLs and you can easily create your own tokens with a bit of PHP code. With Path Auto you can also easily change the URLs for all your nodes, users, and taxonomy terms at once. This is the rope.

A big part of SEO is the link building you do outside of your site to get other sites to link to your site and your inner pages within the site. The problem is when you've done all this and have thousands of links to hundreds of your pages and then you decide to change all of your URLs. Suddenly, visitors to your pages are seeing 404 error pages and Google also no longer thinks you have any linked to pages.

So what can you do if you ever want to change the path of a node after you've already created the node and saved the URL? What can you do once you rebuild your paths from a new pattern? What if your maximum URL length limit was too short and now you need to fix all the long node URLs.

Fortunately, new versions of Path Auto integrate with Path Redirect, which is a module for managing lists of 301 URL redirects. So by hand, you could manually create 301 redirects from the previous alias to a new alias, but luckily you can also do this automatically now. A new option was added to Path Auto to "Create a new alias. Redirect from old alias." Choose this instead of just deleting old aliases and your new node paths should have old paths pointing to them, managed by Path Redirect.

Just remember that bulk update from within Path Auto isn't the only way to update URLs. You can also bulk update selected nodes from the default content management page and also edit the URL from each node's edit page.

To use this, just install both Path Auth and Path Redirect.

Related Issues: http://drupal.org/project/issues/pathauto?text=redirect+from+old+alias&status=All

When manually changing titles and thus URLs make sure to check "Automatically create redirects when URL aliases are changed." in Path Redirect's settings.

Regarding Path Redirect's fixes and Path Auto's fixes:

http://drupal.org/node/629742#comment-4336624


In short: the two work independently.

The option "Automatically create redirect" (on the Path Redirect admin screen) only governs situations where you manually change a path setting. Whether pathauto is or isn't installed, does not change this behavior.

Detail: when saving a node from the edit screen, the Path Redirect code executes before Pathauto does. It has no knowledge of whether Pathauto will or will not change the path alias, later on.

If pathauto runs afterwards and decides that the path needs changing, it will look only at its own "Update action" to determine what to do. If that is "Delete the old alias", it will indeed get deleted, and no redirect will be created (regardless of the "Automatically create redirect" option in the Path Redirect admin screen).

Drupal URLs can be pretty long. But practically, there's a limit in the database of 128 characters, even though browsers and web servers can support much longer URLs. With new versions of Path Auto, the schema is checked for alias column size. Then aliases longer than 128 characters are supported. This requires no hacking!

To change this, without just manually altering the length of the column in your database, you can use the following code in your own module:

/**
* Implementation of hook_schema_alter().
*/
function yourmodulename_schema_alter(&$schema) {
  $schema['url_alias']['fields']['dst']['length'] = 255;
}

Long URLs aren't very human friendly but even the oldest browsers can support URLs more than 2048 characters in length. Browsers support long paths, web servers support them, proxies support them, and mail clients either support them or break around 80 characters anyways. This doesn't mean you should carelessly throw around long URLs, but if you're generating them automatically then you don't need to cut them at an artificially low limit anymore.

Vietnam is blessed with free wifi at nearly any cafe even if it doesn't always work as advertised, like most things in Vietnam. Vietnam is also blessed with cafes on nearly every block. So finding a wireless access point to get online is pretty easy for anyone traveling or living in Vietnam.

Hackers can see what websites you're visiting and then log into those websites as you

The problem is security. Many times cafe owners will leave their wifi access points completely open without needing a password to get on. This makes it basically trivial for a hacker to sniff the airwaves and see everything on the network. If you are on such a network you should secure your connection with an SSH tunnel or a VPN.

If they do have a password, they may be using older security schemes like WEP or WPA, rather than WPA2. Without WPA2 or more secure systems that require the network owner setting up an authentication server (too much to ask for any cafe owner) it is also possible to break the encryption.

Security setting: WPA2

For now, insist on at least WPA2. If you're setting up wifi at your house and you don't want people to sniff your traffic, use WPA2 with a long random password and be sure to change the SSID from the default network name provided by the manufacturer. (The reason that using a default SSID is less secure is that rainbow tables exist for these, making password cracking potentially easy.)

Using WPA2 means that it's harder for crackers to guess your network's password and then either use your network connection or sniff your traffic. But if you give out your password, anyone with the password can do the same. With WPA2 it's harder for other people to sniff your traffic, but there are ways (ARP poisoning) around it. You should thus still create an encrypted connection (for normal people I would recommend using a VPN) to an outside server and tunnel your traffic over that connection.

Besides sniffing your traffic, a hacker who steals your cookies can then login to websites which you're currently logged in by pretending to be your computer. So they could post on Facebook as you, send emails as you from Gmail, or worse.

MAC Address Filtering

What else can you do on your home wifi network? Since you usually know what computers you want to allow to access the wifi router, you can set it so only known computers are allowed on the network by using MAC address filtering. The MAC address the hardware address built into your wireless card or in the wireless hardware of a laptop and it's very difficult to lie about what your MAC address is so this will help keep the riff raff out.

Advanced users can install DD-WRT or OpenWRT firmwares onto their wireless access point, thus enabling tons of extra features and the ability for finer grained security controls.

Using Google AdSense in Drupal

Submitted by tomo on October 8, 2012 - 10:11pm

Recently I attended a BarCamp where there was a session about monetizing blogs for a very modest monthly income, although an amount that amounts to a lot for a local blogger. With Drupal, setting up Google AdSense content is easy.

First, just copy the code generated from Adsense into a new block using the block admin interface. Be sure to save the node with the PHP Input Filter (you may need to give yourself permission in admin/permissions to use this powerful filter). Full HTML filter is not sufficient for AdSense code as it will break the finicky JavaScript, so use PHP which performs no filtering or transformations or create a new input filter that does no filtering.

You may want to create a special region (by editing the .info file for your theme and adding a new line, then refreshing cache to see it in the dropdown in blocks admin) for your ads otherwise use an existing region to place the block. If you already have regions like a sidebar that has space for content in the same dimensions (especially width) as your chosen AdSense ad then you won't need to do anything. If you want to optimize your ads though it's recommended, even by Google themselves, to choose larger ad sizes - especially large square ads.

For placing the node somewhere within the node's content, it's trickier as you can't place it use the block admin interface which only deals with regions that are defined in .info and made available via preprocess functions to your page.tpl.php. You can still use blocks to contain the code though. So create a new block, then look for the number in the URL which is the block id. Then you can manually place that block's content anywhere with this code:

$block = module_invoke('block', 'block', 'view', <BLOCK_ID_HERE>);
print $block['content'];

When publishing your ad blocks, if they don't appear at first and you see "Bad Request 400" in Chrome's Developer JavaScript Console, you can try waiting and may magically go away after awhile. That's what happened to me.

There's also an AdSense module (http://drupal.org/project/adsense) which makes this all a bit easier, but as you can see it's not hard at all to do manually, which means one less module on your system to complicate things.

But here are some other things the Drupal AdSense module can do:


The module provides easy-to-use ad blocks.
You can easily disable the ads for certain roles.
Provides simple controls for troubleshooting the ads before going live with the site.
If Google changes some minor details in the script in , your script can be updated site-wide just by upgrading the module.
If you want to do ad revenue sharing, there's really no other option

This technique can be used for other online advertising networks besides Google AdSense. It could just as easily be used for Amazon.com's affiliate program. If you're in Vietnam you might consider one of the burgeoning number of Vietnamese online ad networks, although they won't have anything like the inventory of Google.

Vietnam Online Ad Networks

Submitted by tomo on October 8, 2012 - 10:10pm

What to do if you're a content provider in Vietnam?

If you're fairly established as a Party-affiliated Vietnamese newspaper then you have probably been selling banner ads for years on your online properties. Maybe you have enough online properties that they constitute a small ad hoc online ad network which you can sell to advertisers. If you're smaller than that then you should be concentrating on producing content rather than developing the ad selling product. So you'd need to find some service to take care of selling your available ad space inventory.

How online ads are sold outside of Vietnam

The first online ad marketplace that should come to anyone's mind is Google with its AdWords and AdSense products (which complement each other as supply and demand). I've played around with Google AdSense (the advertising product for publishers) on this site but it may not be appropriate for Vietnamese publishers. As an American it's easy for me to connect to the US financial system. Vietnamese people would have trouble opening up a US bank and the Vietnamese banking system is barely connected to itself (making homegrown PayPal clones even more difficult to pull off) much less to the US or international banking system. It's hard to move money into and out of Vietnam, although regulations make inflows of cash much easier than outflows. And due to the large amount of fraud originating from Vietnam it's hard to get outsiders to allow normal Vietnamese people to receive money, since once it enters Vietnam it's hard to get it back out if there are any problems, outside of the remittance networks. Until very recently it wasn't possible to use PayPal as a Vietnamese person here and it's still extremely rare.

If you're one of Vietnam's major publishers then you don't care too much about homegrown ad networks since they only reduce your monopoly on ad space, while pushing down prices and encouraging transparency which could force you to be more honest about your product and push prices down even further.

Vietnamese ad networks for Vietnamese content websites!

But having more available ad networks to Vietnamese content producers helps develop a strong web ecosystem for and by Vietnamese people, giving them ways to earn money both domestically and from foreign companies wanting to market to Vietnam. Blogs and other content websites could potentially give Vietnam's economy a tiny push in the right direction although currently it's risky to plan a business around content websites in Vietnam for a number of reasons and monetization is just one of them. (Just recently, Zing, a large content network with news, a social network, and lots of downloadable but unlicensed (pirated) music got dropped by major advertisers like Samsung, Coca Cola, Canon, Yamaha, Intel, etc. precisely because of the latter - they didn't want to associate themselves with an illegal music downloading site, but without the mp3s it would be hard for Zing to get traffic.)

So without further ado here are the online ad networks in and targeting Vietnam:

- ComScore put Innity in first place (of only two measured competitors?) for ad network size in Vietnam in February of 2011 with 900,000 average daily visitors. I really can't say whether Innity, from Malaysia and serving all of Southeast Asia, is the biggest ad network running in Vietnam.

- VietAd, part of IDG Vietnam's portfolio, running since May of 2007. According to them:
"VietAd Ad-Network is an intermediate system connecting sellers and buyers of online advertising. In other words, VietAd operates as an trading platform helping website owners to sell advertising, individuals and enterprises to advertises; both of them can save time and cost while they still have effective advertising campaigns."

"After more than two years on the market, VietAd attracted nearly 1,000 quality media, news, commentary and entertainment websites in Vietnam, served more than 3 billion Ad views and reached 400 million website hits per month."

- AdMarket, a product from AdMicro which is part of BarCamp Saigon sponsor VC Corp. (not to be confused with MicroAd which just entered Vietnam from Japan). Online advertising from 900đ/click and reaching up to 25 million people.

- AdNet.vn from PeaceSoft (NganLuong, eBay.vn, ChoDienTu)

- Ambient Digital Network (minimum payout payment of 300,000 VND) based in Ho Chi Minh City.

- VietBUZZad

- AdMax Network in South East Asia, based in Singapore

- AdBay, partner of PeaceSoft and VietBUZZad.

- AdBay.vn in Hanoi

- CleverAds, a local Google AdWords partner who helps companies set up their AdWords campaigns, also claim to have their own AdNetwork.

- Some hints of an ad network (Fmob) coming from Joomlart. Will have to ask him about that soon.

- New from FPT, eClick.vn

As mentioned, large news sites have their own ad networks. I skipped some really pathetically small ad networks. If you have anything to share about the ad networks listed above -please- post a comment. :)

One question I have and I welcome any theories:
How long before MJ Group (NhomMua, DiaDiem) or Rocket Internet, both big consumers of online ad space in Vietnam, decide to roll their own ad networks?

Syndicate content
© 2010-2014 Saigonist.