Improving Your Copy
Copy - Material, such as a manuscript, that is to be set in type.
The next feature I want for article mode is for it to be able to help you to write good copy. Sounds impossible? Well, copyblogger has an article with some rules you can follow.
To get started, just delete the word very. While you’re at it, get rid of cowardly qualifiers like "it seems" or "just might be" or "could be considered." Wimpiness is for first drafts. If it helps you to visualize Hans and Franz at this point, feel free.
I’d like something that highlights these cowardly qualifiers and perhaps also sentences that are too long (like this one) along with commands to move between the sections of problematic copy.
(defvar am-max-sentence-len 25) (defvar am-copy-positions nil) (defvar am-current-pos -1) (defvar am-copy-qualifiers (concat "very\\|" "it seems\\|" "just might be\\|" "could be considered\\|" "that\\|" "really\\|" "just"))
am-copy-positions will store the locations as a vector that we can move forwards and backwards along and am-current-pos will index into that vector.
(defun am-add-copy-issue (start end) (let ((marker-start (make-marker)) (marker-end (make-marker))) (set-marker marker-start start) (set-marker marker-end end) (push (cons marker-start marker-end) am-copy-positions)) (am-add-overlay start end 'am-copy-face))
When a problem is found there are two jobs to do - store the location and add the overlay. In the interests of DRY there is a single function, am-add-copy-issue that does both. (am-add-copy-issue ...) stores the start and end of the suspect copy as markers1. I don’t really need the end position at the moment but I am considering of adding a command to easily delete the issue too.
(defun am-highlight-long-sentences () (interactive) (save-excursion (let (start end matches) (goto-char (point-min)) (setq start (point)) (while (< start (point-max)) (forward-sentence) (setq end (point)) (when (> (count-matches *am-re-word* start end) am-max-sentence-len) (am-add-copy-issue start end)) (setq start end))))) (defun am-highlight-qualifiers () (save-excursion (goto-char (point-min)) (while (re-search-forward am-copy-qualifiers nil t) (am-add-copy-issue (match-beginning 0) (match-end 0)))))
am-change-copy-highlight is a helper function for moving between the sections of bad copy. It checks if the bad copy check is active and if we are at the first / last section before amending the index. am-next-copy-highlight and am-previous-copy-highlight then call this with a -1 or a +1 offset respectively.
(defun am-change-copy-highlight (offset) (let (newpos) (when (numberp am-current-pos) (setq newpos (+ am-current-pos offset))) (cond ((not am-copy-positions) (message "Error: copywriting check not active")) ((or (< newpos 0) (> (1+ newpos) (length am-copy-positions))) (message (format (concat "Error: am-current-pos not " "a valid index (%s %s)") newpos offset))) (t (progn (setq am-current-pos newpos) (goto-char (car (elt am-copy-positions newpos)))))))) (defun am-next-copy-highlight () (interactive) (am-change-copy-highlight -1)) (defun am-previous-copy-highlight () (interactive) (am-change-copy-highlight 1)) (defun am-reset-copy-highlight () (interactive) (setq am-current-pos (length am-copy-positions)) (am-change-copy-highlight -1))
am-check-copy-start resets the positions and highlights the long sentences and suspect qualifiers. vconcat can be used for converting lists into vectors. am-check-copy-stop resets the variables and deletes the overlays.
(vconcat &rest SEQUENCES)
Concatenate all the arguments and make the result a vector.
The result is a vector whose elements are the elements of all the arguments.
(defun am-check-copy-start () (interactive) (setq am-copy-positions nil) (am-highlight-long-sentences) (am-highlight-qualifiers) (setq am-copy-positions (vconcat am-copy-positions) am-current-pos (length am-copy-positions)) (am-reset-copy-highlight)) (defun am-check-copy-stop () (interactive) (setq am-copy-positions nil am-current-pos nil) (am-delete-overlays))
And which keys should I use for each of the features? Perhaps these ones?
(define-key article-mode-keymap (kbd "C-x C-l") 'am-check-copy-start) (define-key article-mode-keymap (kbd "C-x C-n") 'am-next-copy-highlight) (define-key article-mode-keymap (kbd "C-x C-p") 'am-previous-copy-highlight) (define-key article-mode-keymap (kbd "C-x C-r") 'am-reset-copy-highlight)))
1. Markers are updated so that they keep pointing to the same thing when the text before them changes. They are necessary in this case as I imagine that the bad copy will often need to be changed.
Count Active Region Words - Another Article Mode Enhancement
As I mentioned previously I wanted to add a feature to article mode that would count the number of words in an active region. I can’t think of an immediate practical purpose, but I am frequently curious how long a paragraph is. If the feature has been implemented correctly, I can tell you that this one, for example, is around sixty-nine words long depending on your definition of a word.
To fit in with the rest of the mode, it would be nice if the information was automatically displayed when the region is active. There are two likely candidate hooks - activate-mark-hook and deactivate-mark-hook which look promising. However, on experimentation with activate-mark-hook, it didn’t really work as I wanted.
activate-mark-hook documentation
Hook run when the mark becomes active. It is also run at the end of a command, if the mark is active and it is possible that the region may have changed.
What I really want is that when a region is active I may need to recalculate the number of words in that region whenever a command is executed.
When the mark is active, record the start and end of the region and restart the timer to update the info window.
post-command-hook is ideal for this and I can literally express my intent line for line in the code. I’m not happy with my naming convention for the functions that are run by the hook variables as they can be mistaken for hooks themselves but I’m not feeling very inspired.
(defun am-post-command-hook () (when mark-active (setq am-region-beginning (region-beginning)) (setq am-region-end (region-end)) (am-restart-timer)))
am-region-beginning and am-region-end are variables we defined earlier and I decided to immediately remove the region word count when the mark becomes inactive.
(defvar am-region-beginning nil) (defvar am-region-end nil) (defun am-deactivate-mark-hook () (setq am-region-beginning nil) (setq am-region-end nil) (when (timerp am-timer) (cancel-timer am-timer)) (am-update-info))
am-update-info is then updated to add the new information if it is available. The statistics need to be gathered before we switch into the info buffer as otherwise we are uselessly measuring the statistics of the info buffer itself. It might have been nicer to write this all into a string before calling a function that just updates the info buffer here. But, hey it works.
(defun am-update-info () ... (let ((words (count-matches *am-re-word* (point-min) (point-max))) (keywords (if (= (length am-keywords-regex) 0) 0 (count-matches am-keywords-regex (point-min) (point-max))))) ... (insert (format "# Words : (%s%s)\n" (if region-words (format "%s / " region-words) "") words)) ...)
The code for restarting the timer is abstracted out into its own function as I seem to be calling it from multiple places. The DRY folks should be pleased.
(defun am-restart-timer () (when (timerp am-timer) (cancel-timer am-timer)) (setq am-timer (run-with-timer am-update-time nil 'am-run-timer-hook)))
All that now remains is to add the hooks in article-mode-start and remove the hooks in article-mode-stop.
(add-hook 'post-command-hook 'am-post-command-hook nil t) (add-hook 'deactivate-mark-hook 'am-deactivate-mark-hook nil t) (remove-hook 'post-command-hook 'am-post-command-hook) (remove-hook 'deactivate-mark-hook 'am-deactivate-mark-hook)
The latest code is in the usual place. Thanks for reading.
Emacs Faces - Using Overlays
I mentioned last time that (add-text-properties ...) doesn’t usually work in a buffer with font-lock activated. How then can we highlight keywords in the general case?
I didn’t know the answer myself before I started implementing article mode, so I looked at a minor mode that does correctly highlight words in a font-locked buffer - flyspell-mode I opened the code by typing C-h f flyspell-mode<RET> and then clicking on the `flyspell.el' part of the resultant document.
flyspell uses overlays to highlight misspelled and duplicate words. It specifies the properties of the highlights using defface. You can see in the code below I’m a lazy commenter.
(defvar am-overlays nil) (defface article-keyword-face '((((class color)) (:background "yellow" :foreground "black" :bold t)) (t (:bold t))) "Article mode keyword face")
Let me explain defface as I found the relevant emacs manual section slightly confusing on first reading. A face can appear differently depending on the properties of the terminal it is displayed on. e.g. a vt100 terminal won’t have colours available whereas a GUI will.
I’ve highlighted a couple of sections here - ((class color)) means the face will look like this on a colour terminal. The (t …) section is a fall through and matches if nothing else did.
(defun am-add-overlay (begin end) (let ((overlay (make-overlay begin end))) (overlay-put overlay 'face 'am-keyword-face) (push overlay am-overlays))) (defun am-delete-overlays () (dolist (overlay am-overlays) (delete-overlay overlay)) (setq am-overlays nil))
Okay, here I’ve defined functions to highlight a single region and to delete all overlays as this will tie in well with the original functions that made similar calls to (add-text-properties ...) and (remove-text-properties ...)
You can see how the new functions substituted in (am-highlight-keywords) and (am-remove-highlight) below.
Before
(while (re-search-forward am-keywords-regex nil t)
(add-text-properties (match-beginning 1)
(match-end 1)
'(face highlight)))
After
(while (re-search-forward am-keywords-regex nil t)
(am-add-overlay (match-beginning 1) (match-end 1)))
Before
(defun am-remove-highlight () (remove-text-properties (point-min) (point-max) '(face highlight))
After
(defun am-remove-highlight () (am-delete-overlays)
Here is the new article-mode.
An Emacs Minor Mode
(aka the Article Mode conversion)
Emacs has a convenience macro for defining minor modes called (appropriately enough) (define-minor-mode ...). It takes a few handy keywords, e.g. :lighter to define that identifier in the mode line and :keymap to define the keymap and the body is executed every time article mode is activated or deactivated.
The new core of my article mode now looks like this:
(define-minor-mode article-mode "Minor mode to assist writing articles." :lighter " Article" :keymap article-mode-keymap (if article-mode (article-mode-start) (article-mode-stop)))
What else has changed?
- Keyword highlights are only removed after a change, rather than after any keystroke (e.g. scrolling)
- The info window is deleted on exiting article mode
And that is about it. I’ve also made a few tweaks to make the updating of the info window a little more reliable.
Let me show you the -start and -stop functions.
(defun article-mode-start () (am-add-info-window) (am-update-info) (add-hook 'after-change-functions 'am-after-change-functions-hook nil t) (add-hook 'am-timer-hook 'am-update-info nil t) nil) (defun article-mode-stop () (remove-hook 'after-change-functions 'am-after-change-functions-hook) (remove-hook 'am-timer-hook 'am-update-info) (delete-window am-info-window) (setq am-info-window nil))
As you can see, they are both pretty simple. The -start function adds the info window and immediately updates it so that it is current. Then it adds a buffer-local1 hook to after-change-functions. This hook kicks off a timer that runs the hooks in am-run-timer-hook when emacs is idle for two seconds2. The reasoning behind this is that (am-update-info) will eventually be a fairly expensive function and we don’t want to run it after every change in the buffer.
(defun am-run-timer-hook () (run-hooks 'am-timer-hook)) (defun am-after-change-functions-hook (begin end length) (when article-mode (when (timerp am-timer) (cancel-timer am-timer)) (setq am-timer (run-with-timer am-update-time nil 'am-run-timer-hook))))
Unfortunately, the conversion to a minor mode has highlighted (if you’ll pardon the pun) a shortcoming of the original implementation. We used (add-text-properties ...) to highlight the keywords but this doesn’t generally work if font-lock is activated in the buffer. We’ll discuss how to fix this in the next post.
Here is the updated article-mode.el.
1. The fourth parameter to (add-hook ...) makes a hook buffer-local if it is non-nil.
2. Why not use idle timer? I only want the hook to run after activity in the article mode buffer.
Plans to Improve Article Mode
Okay, I can’t leave well enough alone. I’ve spent around two hours writing my article mode. This has (depending on your point of view), either wasted two hours, or saved $19.95 (for an alternative tool). Now I’m about to pour countless hours more of my already scarce free time into perfecting the tool. Um, hooray?
First things first. It is probably a good idea to have a plan where I am going with this. So, which additional features do I want? The first problem is that my workflow is inefficient. I spend far too long going from article to HTML.
I use muse and htmlize for my HTML generation. However, htmlize is not currently compatible with Emacs23 (and I love the beautiful fonts). Therefore, I have been writing my articles in article mode and then switching to Emacs22 to generate the HTML. Pretty darn slow. Fortunately it is easy to fix. There is a patched version of htmlize that works with Emacs23. And a sigh of relief was heard all round.
The next thing to do, as has been commented on, is to port article mode to a minor mode so it can co-exist with muse. After that, which additional features would I like?
- One-key HTML generation would be handy.
- It would be nice to be able to count the words just in the active region.
- I should have some form of grammar analysis available.
- I would like to have some default empty templates, maybe with my bio at the bottom of the article.
- The fixed window at the bottom of the article is inflexible. Might it be worth changing this to some form of floating frame à la speedbar?
I also considered incorporating kind of article spinning tool but I don’t think I agree with the idea of generating lots of similar articles so I won’t be facilitating that.
I’ll be blogging about updates tothe article writer over the next few posts. Does anyone have any suggestions for additions to the perfect article writing tool?
Saving Time - A Change Of Focus For The Blog
I’ve decided on a change of focus for the blog. Affiliate marketing just isn’t something I feel comfortable writing about at the moment. What I didn’t realise until I thought about it is that saving time (particularly my own) is what I am really interested in.
The obvious way to save time is reduce time spent on tasks that you don’t want to do. For example, I don’t like washing dishes and I’m not very good at it so it normally takes me a while. I think it would probably be worth it for me to invest in a dishwasher.
For some things, there isn’t a convenient gadget you can buy that will do it for you. Sadly, the robot hasn’t yet been created that will clean and tidy a house. However, you can still save this time by outsourcing the cleaning.
This also explains the interest in affiliate marketing. Time saving devices and outsourcing cost money which I can’t currently spare.
One tool that I use a lot to save my time and my companies time is the text editor, emacs. Emacs allows almost infinite customisability. I’ve already mentioned article mode but I have a few other emacs-based time saving tools that I want to talk about over the next few weeks.
What is the Difference Between wordpress.com and wordpress.org?
The answer to this question is pretty clear - wordpress.com is a mostly free host for wordpress blogs and wordpress.org hosts the software itself which enables you to set up your own self-hosted blog. So my question is really What is the difference between hosting your blog at wordpress.com and self-hosting a blog based on wordpress? And the answer is, quite a lot.
First of all, let’s look at the advantages of wordpress.com:
- They automatically update wordpress for you when the latest version is shipped.
- [Presumably] they do a good job of load-balancing so that when your latest post goes viral, your blog stays available.
- It is free (for the basic package)
And the disadvantages:
- No plugins sniff
- RSS feeds on your theme probably don’t link to feedburner
- As far as I know, you can’t access the google webmaster statistics which shows average pageviews and bounce rate.
- If a theme you like isn’t available, you’re out of luck.
- No way to modify the theme beyond access to the CSS if you pay for that upgrade. e.g. if the theme doesn’t include your tagline that’s tough.
- If you violate the terms and conditions, your blog may be deleted.
- …and some terms concerning advertising
The lack of access to the CSS / Themes means that you probably need to add inline CSS and set the widgets up if you want to get close to the look that you want.
self-hosting fixes all of the disadvantages, and if you ever expect your blog to be successful, I strongly recommend it.
As you may have noticed, this wordpress blog is self-hosted, so why am I talking about wordpress.com. Well, I’ve recently acquired a wordpress.com blog which has both (a little) traffic and pagerank and talks about programming - something I’m interested in. I would enjoy making on-topic posts to that blog. Some early experimentation has shown that the blog can rank well for keywords much more easily than this timepoorblogger blog.
I wanted to use the Rubric theme but it doesn’t contain my tagline or any obvious link to the rss feed. Eventually, I settled on the MistyLook theme which fixes those problems.
I wanted a decent set of archives (monthly archives are useless aren’t they?) so I created a page called archives and populated it manually. To do this I set up a blog on my PC using the easy wordpress template script added a clean archives blugin, imported the posts from the wordpress blog (total time 20 minutes) and cut and pasted the archives html across.
I also quite like blogs with a popular posts section in the sidebar. I added a text widget with the title popular posts and set up an unordered list with the most popular posts and views as shown on the wordpress stats page. I’m interested to see if anyone will actually click on these links - it should be fairly obvious from the stats.
A question for the SEO guys, what would you do, if you received a wordpress.com blog with traffic and pagerank?
Web 2.0 Websites and the Pagerank Myth
How often do you see something along the lines of "Squidoo has a pagerank 8. Create a lens to get high quality backlinks." Actually, it doesn’t have to be Squidoo, it could be Hubpages or USFreeAds. I’ve heard it said about a lot of websites.
There are a lot of reasons for using Squidoo which I’ll write about later (with my extensive experience ;)) However, don’t think that you are going to get a PR8 backlink without any effort.
On Squidoo you can take a look at the top lenses. These lenses have had a whole bunch of work put into them (not to mention the effort put into the owners’ other lenses and profiles) and they rank at either PR4 or PR5 - good but not a PR8. The front page gives PR8 links and there are some deep links within it that also have a good pagerank but I’m afraid your newly created lens has a PR0.
So to summarize, if you think that PR8 links are free to every Tom, Dick and Harry on the internet, well, they’re not. And that is a good thing.
| Lens | Pagerank | Traffic |
|---|---|---|
| http://www.squidoo.com/lcd-televisions | 4 | 1,885 |
| http://www.squidoo.com/robert_pattinson | 4 | 6,157 |
| http://www.squidoo.com/workathomewithsquidoo | 5 | 881 |
| http://www.squidoo.com/squidoo-twitterdrive-for-charity | 5 | 312 |
| http://www.squidoo.com/Panini-sandwich-recipes | 5 | 7,635 |
Pagerank is a trademark owned by Google.
PR checked with the prchecker tool.
Keyword Optimization - Extending Emacs for SEO
I read an interesting post about a tool for writing keyword optimized articles on my new favourite blog. Now, potpiegirl has a lot of great information, and every so often she talks about a handy tool and throws a few affiliate links in there. Nice marketing strategy! Anyway, the tool’s features that she mentioned do sound handy.
- Check keyword density
- Check spelling
- Show word count
- Save content as either text or HTML
- Highlight keywords
I like to use a pretty geeky tool called emacs for almost all my content generation. The tool was created in the seventies before any such thing as keyword optimization. However, it fits me like an old glove - I feel really productive when using it. And it does allow a dedicated user to add almost any functionality they might want.
There are already third party extensions to add on the fly spellcheck and easy HTML generation which just leaves word count keyword density and highlighting.
The basic plan is to have a small frame at the bottom of the editor which constantly updates with the number of words and keyword density. Highlighting will be controlled by a key combination and disabled when any other key is pressed.
We need to explain to emacs what a word is (so it can count them) and we also need a name for the buffer at the bottom of the window.
(defconst *ac-re-word* "\\(\\b[-A-Za-z0-9_]+\\b\\)") (defconst *ac-info-buffer-name* "*article-info*")
We will need a timer as we won’t want to update the information after every keystroke. Providing a hook for the variable means that other people will be able to add their own functionality when the timer fires.
We also need somewhere to store the keywords and a variable to indicate whether the keywords are highlighted or not.
(defvar ac-timer nil) (defvar ac-timer-hooks nil) (defvar ac-info-buffer nil) (defvar ac-keywords nil) (defvar ac-keywords-regex nil) (defvar ac-highlighting-on 0)
We’ll want a way to add and remove keywords that are relevant to the article.
(defun ac-set-keyword-regex () (let ((re (mapconcat (lambda (e) e) ac-keywords "\\|"))) (setq ac-keywords-regex (if (> (length re) 0) (concat "\\(" re "\\)") "")))) (defun ac-add-keyword (keyword) (interactive "sKeyword: ") (if (member keyword ac-keywords) (error (format "Error: keyword %s is already present" keyword)) (push keyword ac-keywords) (ac-set-keyword-regex))) (defun ac-remove-keyword (&optional keyword) (interactive) (when (not ac-keywords) (error "Error: no keywords set")) (unless (stringp keyword) (setq keyword (ido-completing-read "Keyword: " ac-keywords nil t nil))) (setq ac-keywords (remove keyword ac-keywords)) (ac-set-keyword-regex))
Highlighting the keywords takes three functions - one to add the highlight, one to remove it and one to toggle it.
(defun ac-highlight-keywords () (when (not ac-keywords) (error "Error: no keywords set")) (save-excursion (goto-char (point-min)) (while (re-search-forward ac-keywords-regex nil t) (add-text-properties (match-beginning 1) (match-end 1) '(face highlight))) (setq ac-highlighting-on 2))) (defun ac-remove-highlight () (remove-text-properties (point-min) (point-max) '(face highlight)) (setq ac-highlighting-on 0)) (defun ac-set-highlight (&optional value) (interactive) (when (not value) (setq value (if (> ac-highlighting-on 0) nil t))) (if value (ac-highlight-keywords) (ac-remove-highlight)))
Populating the information buffer is fairly simple - we clear any text that was there previously and redraw it all. We only need to report keyword density if there are actually some keywords defined.
(defun ac-update-info () (save-excursion (let ((words (count-matches *ac-re-word* (point-min) (point-max))) (keywords (if (= (length ac-keywords-regex) 0) 0 (count-matches ac-keywords-regex (point-min) (point-max))))) (set-buffer ac-info-buffer) (erase-buffer) (insert (format "# Words : %s\n" words)) (when (and (> words 0) (> (length ac-keywords-regex) 0)) (insert (format "# Keywords : %d\n" keywords)) (insert (format "Density : %.2f%%\n" (* (/ keywords (float words)) 100.0)))) (insert (format "Keywords : %s\n" ac-keywords)))))
ac-add-info-window takes care of adding the appropriately sized frame at the bottom of the window.
(defun ac-add-info-window () (interactive) (delete-other-windows) (split-window-vertically (- (window-height) 6)) (other-window 1) (setq ac-info-buffer *ac-info-buffer-name*) (switch-to-buffer ac-info-buffer) (ac-update-info) (other-window -1))
We set a timer to fire whenever emacs has been idle for half a second. The timer runs all the hooks in the hook variable to allow additional user customisation.
(defun ac-run-timer-hooks () (run-hooks 'ac-timer-hooks)) (defun ac-add-timer () (setq ac-timer (run-with-idle-timer 0.5 t 'ac-run-timer-hooks)))
This is fairly standard boiler plate for any derived mode I write for emacs.
(defvar article-mode-hook nil "Hook run when entering article mode.") (defvar article-mode-map nil "Keymap for article major mode.") (define-derived-mode article-mode text-mode "Article" "Major mode for editing articles Special commands: \\{article-mode-map}")
Set up the special keys which the mode uses - one for highlighting keywords and one each for adding and removing them. CTRL-C + <key> is an emacs convention for user commands (so perhaps I shouldn’t be using it - oops! Force of habit)
(if article-mode-map nil (progn (setq article-mode-map (make-sparse-keymap)) (define-key article-mode-map (kbd "C-c a") 'ac-add-keyword) (define-key article-mode-map (kbd "C-c d") 'ac-remove-keyword) (define-key article-mode-map (kbd "C-c h") 'ac-set-highlight)))
Figuring out how to disable the highlight after any key was pressed took the most time. There is an emacs hook that allows you to insert a function each time a key is pressed. However, the obvious thing to do - disabling the highlight, doesn’t work as adding the highlight is a command. It would add the highlight and then the hook would run which would remove it immediately.
I worked around this by setting the highlight flag to 2 when the highlight is set. Then, each time the post command hook fires, this value is decremented. This is more for micro-efficiency so that when the flag is set to 0 we don’t have to remove the highlight on every keypress.
(defun ac-post-command-hook () (cond ((>= ac-highlighting-on 2) (setq ac-highlighting-on 1)) ((and (= ac-highlighting-on 1) (equal major-mode 'article-mode)) (ac-remove-highlight))))
Enabling article mode sets a bunch of things up such as adding the information frame, enabling the on the fly spellcheck and enabling longlines mode. Longlines mode causes the words to wrap around, just as a normal word processor which emacs normally doesn’t do.
(defun ac-article-mode-entry () (add-hook 'post-command-hook 'ac-post-command-hook t) (ac-add-info-window) (flyspell-mode 1) (longlines-mode 1)) (add-hook 'ac-timer-hooks 'ac-update-info) (add-hook 'article-mode-hook 'ac-add-timer) (add-hook 'article-mode-hook 'ac-article-mode-entry) (provide 'article-mode)
And there you go - all done. The majority of the extension was finished in an hour. Getting the highlight to disappear after any keypress (which was an entirely unnecessary feature, but something I wanted) was a bit fiddly and took another hour. But now it’s complete and emacs becomes the perfect tool for writing keyword optimized articles. Yay!
Download article-mode-major.el.
Note: this has now been superseded by a minor mode version. The updated code can be downloaded here.
First Statistics From Squidoo and EzineArticles
I finally have some statistics. I’ve created four Squidoo lenses, one group and one ezine article that has been published. Have I managed to get any traffic?
Two of my lenses appear in the google index. My article, which was published two days ago, refers to one of those lenses (my primary lens). Over the last 7 days the lens with the article referrer received 10 visits and 9 of those where from the ezine article.
Traffic
The article itself received 21 visitors on the first day, 17 on the second and 8 today. I’m fairly curious to see how the traffic tails off but unfortunately I won’t be able to monitor it over the next few days. With such a small amount of traffic I suspect it isn’t significant.
Lens A: 13 (12 from article) Lens B: 2 (referred from Lens A) Lens C: 3 Lens D: 2
Lens A and B are both related as are C are D.
Google Ranking
Both the article and Lens A are targetting the same long tail keyword with around 3,500 competitors. The article is at 16th place (2nd page) for the quoted phrase and the lens is at 21st place (3rd page).
Update (31st): The lens is now on the second page at position 19 and the ezine article is nowhere to be found.
For the unquoted expression the article is at position 21 and the lens is at 34. The phrase gets just a little traffic. It may be worth trying to boost the lens and/or the article onto the first page to see if it gets any traffic directly from google.
The article was indexed by google almost immediately as was Lens A. Lens C was indexed about one week after creation and I have no idea why the other lenses are not indexed.
Lens Rank
Lenses A C and D had a lens rank of between 105,000 and 125,000 when created. Lens B has a lens rank of greater than 165,000. Lens A has been promoted several times and now has a lens rank of better than 20,000. I suspect the increase in lensrank for lens A is due to the traffic I “bought” with my time writing the article.
So, overall, the results are pretty interesting. In this specific case the article handily beats the lens and was much easier to write. Both article and lens have received more traffic than this blog which has had a handful of visitors over its entire life. All pages are indexed in google and the spiders visit fairly frequently.
