Category: Writing

  • Email Data-Science Posts

    The old Mailchimp blog had several classic articles about email. These articles were data driven, and many were written by the fantastic John Foreman (whose book and talk I recommend).

    These articles were scrubbed from the Internet. So here they are again, for private reference:

    John Foreman
    A Purchased List is a Dead List
    Jul 24, 2014 MailChimp prohibits using purchased, rented, or scraped email lists, which are now illegal in Canada under CASL and violate their acceptable use policy. Such lists perform poorly, leading to low engagement and high complaint rates.

    AOL and Hotmail Users Spend More than Gmail Users, and Other Research Finds
    Jan 8, 2013 MailChimp’s 2012 research highlights reveal that Hotmail users tend to spend more than Gmail users, likely due to an older demographic with more disposable income. Additionally, daily deals emails have low engagement but also low unsubscribe and abuse rates, while purchased email lists result in significantly higher complaint rates, leading to potential ISP blocks.

    Comacast and Gmai: all your typo email are belong to us
    Dec 20, 2011 Typos in email addresses, especially in domains, can lead to successful delivery to typosquatting sites, which may result in security risks or misuse of your content. It’s crucial to watch for these errors and consider using double opt-in to ensure list quality.

    Competing with the World Cup for Subscribers’ Attention
    Jul 9, 2014 The 2014 World Cup significantly impacted email marketing engagement, with noticeable drops in activity during games and peaks before and after matches. Marketers should consider their subscribers’ time zones and avoid sending important campaigns during major events to maintain engagement.

    Detecting Click Clusters in Your Data Using Spreadsheet Math
    May 15, 2013 Most people segment their email lists based on predefined criteria, but there’s potential in allowing the computer to analyze data and suggest segments based on subscriber clicks. By employing data mining and unsupervised learning, we can uncover new insights and optimize our email marketing strategies.

    Digging Deeper into Wavelength and EGP Data: Finding Interest Clusters in MailChimp’s Network
    Oct 23, 2012 MailChimp’s Wavelength tool analyzes subscriber data to identify interest clusters among users, enhancing targeted marketing efforts. By employing cosine similarity calculations, it reveals how closely related different subscribers are, uncovering unique audience segments and insights for improved engagement strategies.

    Effect of Social Networks on Email Engagement
    Feb 22, 2011 The article discusses how social networks can enhance email engagement, emphasizing the importance of diverse content sharing on platforms like Twitter and Facebook. Research indicates that incorporating social elements in emails can lead to increased engagement, suggesting that marketers can effectively blend email and social strategies for better results.

    Fun with Data Science
    Dec 7, 2011 The article introduces John, a data scientist at MailChimp, who analyzes email campaign performance through geographic distribution using advanced algorithms like clustering and dendrograms. His findings reveal significant insights on list performance, such as the correlation between subscriber locations and bounce rates, as well as the benefits of utilizing newer email domains for better engagement and deliverability.

    How Gmail Tabs Affect Your Email Marketing: An Update
    Dec 12, 2013 The article discusses the impact of Gmail’s tabbed inbox on email marketing, revealing that while open rates have decreased significantly for Gmail users, the system appears to help users manage their inboxes effectively, as unsubscribe rates remain stable. Additionally, it highlights variations across industries, suggesting that marketers may need to adjust strategies to engage subscribers better.

    Inactive Subscribers are Still Valuable Customers
    Feb 9, 2016 The article emphasizes that inactive subscribers, while not actively engaging with emails, still hold significant value for businesses. They contribute to revenue, purchase more frequently, and are less likely to churn compared to non-subscribers, suggesting that businesses should focus on re-engagement strategies rather than removing them from email lists.

    Insights from MailChimp’s Send Time Optimization System
    Jul 14, 2014 The article discusses MailChimp’s Send Time Optimization (STO) feature, which recommends optimal sending times for email campaigns based on individual engagement data. It highlights key insights such as weekdays being preferable for sending, a peak time of 10 AM, and the importance of understanding the audience’s characteristics, like age and occupation, for effective email timing.

    Introducing Hairball v2: Hairball with a Vengeance
    Apr 9, 2012 The article introduces Hairball v2, an updated version of the Adobe Air application designed for complex list segmentation in MailChimp, allowing users to perform advanced analysis of campaign performance and recipient engagement. Key features include improved segmentation based on historical data, performance comparison, and more precise filtering of click data to enhance targeted marketing efforts.

    Introducing Wavelength
    Jan 18, 2012 Introducing “Wavelength,” a MailChimp service designed to help users find similar publishers by analyzing their email lists. It emphasizes the importance of building organic, permission-based email lists instead of purchasing them and outlines how Wavelength can connect users with relevant newsletters based on subscriber overlap.

    MailChimp’s Email Genome Project
    Feb 9, 2011 The MailChimp Email Genome Project aims to analyze user data to improve email marketing effectiveness and deliverability. By examining patterns from millions of subscribers and emails sent daily, MailChimp seeks to address common dilemmas in email marketing and prevent abuse of the email ecosystem.

    Multivariate Testing for MailChimp Pro
    Sep 17, 2015 The article discusses MailChimp’s new Multivariate Testing feature, which allows users to test up to eight different elements of an email simultaneously to enhance customer engagement and marketing strategies. It emphasizes the importance of data-driven decisions and provides insights into effective testing practices and reporting metrics to optimize email campaigns.

    Project Omnivore: Declassified
    Jan 27, 2010 MailChimp’s Project Omnivore, initiated in late 2008, aimed to create a scalable tool to detect spam, particularly from well-meaning marketers unaware they’re spamming. By utilizing advanced genetic optimization techniques and massive data analysis, Omnivore assesses email campaigns and user behavior, sending warnings or suspending accounts for suspicious activities, while still relying on human review for final decisions.

    Project Omnivore: Three Years of Gorging on Data
    Nov 13, 2012 This article discusses Project Omnivore, which MailChimp launched to monitor and analyze email list quality and sender behavior. By utilizing an AI model that evaluates email addresses based on extensive historical data, Omnivore helps ensure a healthier email ecosystem while allowing legitimate users to send emails without unnecessary barriers.

    Research: Spammy Email Design Mistakes
    Oct 13, 2010 The article discusses an experiment by MailChimp that analyzed email campaigns flagged as spam by reviewers from Amazon’s Mechanical Turk. It identifies common design mistakes that lead to false positives, such as overly sales-oriented text, poor layout, and reliance on stock templates, ultimately providing insights into effective email marketing design.

    Send Time Optimization in MailChimp
    Dec 3, 2013 This HTML document outlines the “Send Time Optimization” feature introduced by MailChimp, which helps users identify the best times to send emails based on subscriber engagement data. The optimization takes into account global email engagement trends and specific subscriber history to improve click-through rates, particularly focusing on the most engaged audience segments.

    Sending Frequency: More Is Not Always Better!
    Apr 23, 2013 This article discusses the misconception that sending more emails leads to greater engagement and revenue. It emphasizes that increased email frequency negatively correlates with engagement per campaign, suggesting an optimal sending frequency to maximize total clicks rather than simply increasing volume.

    Smarter Bounce Management Rules with Engagement
    Sep 1, 2010 The article discusses the challenges of managing email bounces for Email Service Providers (ESPs), emphasizing the distinction between hard and soft bounces and the complications that arise from server errors and deceptive bounce messages. It highlights the importance of effective bounce management for maintaining domain reputation and outlines MailChimp’s strategy of incorporating engagement metrics into bounce cleaning decisions to improve deliverability and list management.

    Subject Line Data: Choose Your Words Wisely
    Nov 13, 2013 This article analyzes the impact of subject line wording on email open rates, revealing that even a single word can significantly affect engagement. Key findings include the effectiveness of personalization, urgency, and certain keywords, highlighting the importance of choosing words wisely in email campaigns.

    Subscriber Engagement Half-Life
    Feb 18, 2011 The article discusses findings from Dan Zarrella’s webinar on email marketing, revealing that the average click rate for subscribers significantly drops below 1% after four months. To maintain engagement, marketers must entertain and deliver value quickly while continually attracting new subscribers to offset potential churn.

    Subscriber Engagement Over Time
    Nov 25, 2013 The article analyzes subscriber engagement over time using extensive data, finding that click rates start above 5% and decline to around 3.5% after multiple campaigns, with differences observed across industries and email domains. It emphasizes the importance of subscriber context and preferences in shaping engagement, recommending strategies like double opt-in to enhance initial interaction levels and maintain interest.

    This Just In: Subject Line Length Means Absolutely Nothing
    Sep 17, 2012 The article explores the misconception that the length of email subject lines significantly affects open and click rates. Analyzing data from 12 billion emails, it concludes that there is no meaningful correlation between subject line length and engagement, emphasizing the importance of personalized content over gimmicks or strict length guidelines.

    Update on Omnivore, new 3 Strikes Rule
    Aug 27, 2010 The article provides an update on MailChimp’s Omnivore program, which is designed to combat email abuse by analyzing user behavior and implementing anti-spam measures. It discusses the new “Three Strikes” rule, stating that if any sender is suspended three times within six months, their account will be permanently shut down, aiming to enhance the overall integrity of the email ecosystem.

    What Does Your ISP Say About You?
    Nov 26, 2013 This article explores how email addresses can reveal insights about individuals, including their likely age and interests based on the email domain used. It analyzes various domains such as Gmail, Hotmail, Yahoo, AOL, and Comcast, showing how different demographic characteristics and preferences can be inferred from users of these services.

    What Good Marketers Can Learn from Spammers
    Oct 18, 2012 The article discusses what effective marketers can learn from spam emails, specifically highlighting that while spammers often use a single clear call to action and few distractions, marketers should balance word count, image count, and URL count to optimize click rates. The research indicates that campaigns with concise content and relevant links tend to perform better than those with excessive text or images, ultimately suggesting that quality and clarity are key to successful email marketing.

    Where Have All the Government Clicks Gone?
    Oct 15, 2013 The article discusses the impact of the 2013 U.S. government shutdown on email engagement among government employees, noting a significant drop in interactions from affected agencies. It highlights how the furloughs led to decreased activity, contrasting it with unaffected agencies like the SEC, which saw increased engagement during the fall marketing season.

  • $21 Refrigerated Rigatoni

    On September 10, 2024 a Linkedin post by Alexandra P. got a lot of interest. The post showed a $21.02 premade refrigerated rigatoni dish being sold in a Toronto grocery store.

    I used my Linkedin post-saving bookmarklet to export the discussion for posterity. Skyrocketing food prices are a top problem for Canadians at the moment.

  • Project Hammer

    PROJECT HAMMER

    Project Goal

    Project Hammer aims to drive more competition and reduce collusion in the Canadian grocery sector.

    To get this done, we will:
    1. Compile a database of historical grocery prices from top grocers’ websites.
    2. Make the database available in a format that is suitable for academic analysis and for legal action.
    3. Inform changemakers of the existence of this dataset (and make it reasonably easy for them to use).

    Canadian Grocery Price Data

    8 vendors in the dataset: Voila, T&T, Loblaws, No Frills, Metro, Galleria, Walmart and Save-On-Foods.
    Dates available: from February 28, 2024 to the latest load at

    Get Full Data in 2 CSV Files

    The “product” file contains metadata and product details. The “raw” file contains time-series price data. Join them on “id” and “product_id” columns.


    All Data in a SQLite file

    I recommend the free DB Browser software for viewing the SQLite file. It can easily filter the data and export to CSV.


    Learn more about the data fields and how the data was gathered.

    I Need Your Help

    I can’t do this alone. This project can only succeed with a community of people around it – people like you, who bring their own skills and perspectives to the challenge.

    Reach out to me (email “jacob” at this website) if:

    • You can do economic analysis of pricing data, and especially the interaction/correlation of multiple streams of prices across time
    • You are skilled with data processing and normalization
    • You’d play with the data for 1 day and tell me of all the bugs/issues/opportunities you found
    • You are doing similar pricing work in other countries / you’ve been inspired by Mario Zechner’s work
    • You are a data-oriented politician, aide, activist, journalist or lawyer who’s interested in improving Canada’s hyper-concentrated grocery sector
    Source: Competition Bureau Retail Grocery Market Study Report, June 27, 2023

    Price Visualizations from the Dataset

    Full interactive page for the below visualization

    Full interactive page for the below

    Research Questions

    Here are some ideas to play with when looking at the data:

    • Visualize the price of making a standard sandwich at each of the grocers (200g white bread + 20g ham + 20g lettuce...) Which grocer is cheapest?
    • Will there be a Nov. 1 to Feb. 5 price freeze on certain products?:
      Metro stated that “It is an industry practice to have a price freeze from Nov. 1 to Feb. 5 for all private label and national brand grocery products, and this will be the case in all Metro outlets.”
    • When a product goes on "sale", how long has it been since the previous sale? (if something is constantly on sale, then that's just its regular price)
    • When something's on "sale", did the price get jacked up artificially just ahead of the sale, only to lower it back down to normal?
    • How are different grocers responding to each other's price moves, on a certain product/category?
      • Is someone always leading price movements, and the others follow?
      • Is one retailer always reacting, and never initiates price moves?
      • Do prices for certain grocers move exactly in tandem?
      • Do prices move completely at random, with no interaction?
      • Do prices always rise, and never fall?
    • Which grocer is generally the cheapest across all comparable product families?
    • Do prices on certain "bundles of products" always move in tandem, at a single grocer? (think eggs, milk and bread always rising/dropping by similar amounts together)

    Notes About the Data

    Which grocery vendors' prices are included?
    Voila, T&T, Loblaws, No Frills, Metro, Galleria, Walmart Canada, Save-On-Foods.

    How was the data gathered?
    This information is from a screen-scrape of website UI - that's why it is missing information that you might get from the internal APIs that power grocers' websites.

    Prices are for the "in store pickup" option, as set for a neighbourhood in Toronto.

    Is there data for every day and every vendor?
    No. Between Feb. 28 and July 10/11, I was gathering prices for a "small basket" of products. After that, we have prices for a much larger variety of products. Also, there may be missing data for certain days for certain vendors - days on which those specific extracts failed.

    What are the columns in the data?

    Table: product
    Product meta-data like name, vendor (ex. Loblaws), brand and unit size. Is updated only when a new product is discovered (ex. there is a Unit size variation that hasn't been seen before).

    ColumnDescription
    idThis is a unique product ID that's being used to join the "product" table to the "raw" table. This ID changes every day and is not a stable unique identifier! Use SKU or UPC instead when referring to a unique product.
    concattedA homebrew "unique identifier" that concatenates vendor,product_name,unit and brand. Used in intermediate steps before the scrape and the final output.
    vendorOne of the 8 grocery vendors
    product_nameProduct name. May include Brand, may include Units in it.
    unitsUnits (grams, kg, number of items in package). May be blank for some vendors/products.
    brandBrand name of the company that made a product (ex. "Frito Lay"), may be empty.
    detail_url"Detailed product listing URL" for this particular product. Used as a way of extracting the SKU and UPC.
    skuEach vendor's own unique identifier for a given product. Extracted from the "detail_url". For Metro, Galleria and Save-On-Foods, the SKU is also the UPC.
    upcThe universal, cross-vendor unique product identifier. UPC is very hard to find for products.
    Most reliable UPC: Metro, Galleria and Save-On-Foods - their UPCs come directly from the vendor website. Next most reliable UPC: Walmart. The Walmart SKU was matched to a UPC figure on a site that I believe is owned by Walmart. These UPC are from exact matches, not fuzzy matches.
    Least reliable UPC: Loblaws, NoFrills, T&T and Voila. For them, I had to use fuzzy matching to find potential UPCs. I've done a manual Quality Control pass, but there may be incorrect UPCs there - always sanity-check by looking at product_name when comparing across vendors.

    Table: raw
    Product prices at a point-in-time. New data is added every day.

    ColumnDescription
    nowtimeTimestamp indicating when the data was gathered
    current_pricePrice at time of extract
    old_priceAn "old" struck-out price. This indicates that there was a Sale on. This is how you can differentiate a price-drop advertised as a Sale vs. a "quiet" decrease without a Sale.
    price_per_unitPrice per unit, as shown on the vendor website. May not be consistent with real calculation of "current_price" divided by "units". Double check it.
    otherOther details that appeared on the listing. Values may be "Out of stock", "SALE", "Best seller", "$5.00 MIN 2"
    product_idThis is a unique product ID that's being used to join the "product" table to the "raw" table. This ID changes every day and is not a stable unique identifier! Use SKU or UPC instead when referring to a unique product.

    CSV file notes
    The .csv file you get from the form is optimized for Excel. Specifically, it includes a "BOM" - several characters at the start of the file that make Excel treat it as UTF-8. If you're loading the .csv into a different tool for analysis, you may need to remove the BOM.

    SQLite file notes

    • product table: this table contains vendor, product_name, units and brand
    • raw table: contains the time series price data - nowtime, current_price, old_price, price_per_unit
    • The two tables are joined using product.id and raw.product_id
    • To speed things up, there is an index on raw.product_id

    Simple example of how you'd grab all product data for the Becel brand. Note that for certain vendors, "Becel" would only be present in product_name, for others - only in the brand:

    SELECT nowtime, vendor, product_id, product_name, brand, current_price, old_price, units, price_per_unit, other 
    	FROM raw 
    	INNER JOIN product 
    	ON raw.product_id = product.id 
    	WHERE product.product_name LIKE '%becel%' OR product.brand LIKE '%becel%';
    

    Here's a more complex example of how you'd grab prices for all Miss Vickie's Original Recipe chips:

    SELECT nowtime, vendor, product_id, product_name, brand, current_price, old_price, units, price_per_unit, other 
    	FROM raw 
    	INNER JOIN product 
    	ON raw.product_id = product.id 
    	WHERE
    		(product.product_name LIKE '%original%' AND product.brand LIKE '%miss vick%') OR
    		(product.product_name LIKE '%miss vick%original%');

    Why does the query say "miss vick"?
    It's because some grocers represent it as "Miss Vickies", "Miss Vickie's" and some as "Miss Vickie`s" with a weird UTF-8 quote that's not even on your keyboard. "miss vick" matches all of them. Here are the various products from the product table that the above statement will include:

    Note how there are 3 distinct products here at different weights: 59g, 200g and 275g. To compare across vendors, you can refine your SQL query further or export to CSV for filtering in Excel.
    I exported the results of the query above to Excel, kept only the 200g prices, created a PivotChart and got this workable visualization. You can see that Walmart has the lowest prices for Miss Vickies' Original Kettle Chips & the Asian-focused grocers have the highest.

    SQL Code for Reference

    Dear reader - let me know if sharing code,data & notes in an SQL Notebook like Deepnote would be better.

    Prices at June 10 vs. Sept. 17

    Show the price on June 10 (our first full extract) vs. the same product's price on Sept. 17.

    WITH
    	startend_diffrows AS (	-- the price at the first date and last date we want is on different rows (so there are 2 rows for a product that's in our DB on both days
    		SELECT
    			product.*
    			, raw.nowtime
    			, CASE 
    					WHEN raw.nowtime LIKE '2024-06-11%' THEN raw.current_price 
    					END startprice
    			, CASE
    					WHEN raw.nowtime LIKE '2024-09-17%' THEN raw.current_price 
    					END endprice
    		FROM
    			product
    		INNER JOIN raw
    				ON raw.product_id = product.id
    		WHERE
    			raw.nowtime LIKE '2024-06-11%' OR raw.nowtime LIKE '2024-09-17%'),
    	startend_pivoted AS (	-- group the data so that the data from the 2 rows for our unique product ends up on the same 1 row
    		SELECT 
    			id, vendor, product_name,units,brand, MAX(startprice) AS g_startprice, MAX(endprice) AS g_endprice 
    			-- note that there may be several rows for the same produt on the same date - because I ran the extract in the morning and late at night on the same date...
    		FROM
    			startend_diffrows
    		GROUP BY id )
    								
    	SELECT * FROM startend_pivoted -- now drop any products that weren't present on both days in the range (due to scraping failure etc.)
    		WHERE g_startprice NOT NULL AND g_endprice NOT NULL;
    							

    Max, Min, Avg and Count for Prices

    WITH
    	uniquedates AS (
    		SELECT DISTINCT 
    			date(nowtime), current_price, product_id 
    		FROM
    			raw),
    	
    	stats AS (
    		SELECT
    			*, MAX(current_price) as _max, MIN(current_price) as _min, AVG( current_price ) as _avg, COUNT( current_price ) as _count
    		FROM
    			uniquedates
    		GROUP BY
    			product_id)
    			
    	SELECT
    		product.id,product.vendor,product.product_name,product.units,product.brand, stats._max, stats._min, stats._avg, stats._count
    	FROM
    		stats
    	INNER JOIN
    		product
    	ON stats.product_id = product.id;

    Known Issues

    What you see: 2 different price points for the same product, scraped on the same day (and sometimes at the same minute)
    Examples: "100% Natural Origin Moisturizing Lip Balm, Cucumber Mint" and "Melatonin" by Sisu at Loblaws.
    Cause: 2 distinct products are listed on vendor website with the exact same name and "unit size" Up until Sept. 30, 2024 there is no way to distinguish the two. After that, we have unique "detail_url" and "sku" values that help tell them apart.

    What you see: multiple price entries (same price) for the same product on 1 day.
    Magnitude: about 6,500 products impacted per day (as at Nov. 2, 2024).
    Examples: "Mexican 4 Cheeze Blend Gluten Free Shreds" by Daiya at Metro.
    Cause: Sometimes the exact same product appears in the scrape multiple times on the same day. This might be because of a product being listed under multiple categories. Or because the product is being advertised, so it shows up in unrelated categories/stickied on top of page on each page of a category.

    Relevant SQL
    SELECT product_id, COUNT(product_id) AS mycount FROM raw WHERE nowtime LIKE '2024-10-27%' GROUP BY product_id ORDER BY mycount DESC;


    What you see: on the Save-On-Foods extract, some product name + brand combindations are mismatched with the value in detail_url. On extracts up until 2024-12-24
    Magnitude: about 9 products a day, out of ~10k products. But each day, it can be a set of different products.
    Examples: here's an example where the product name doesn't match the units - it indicates that something went wrong:

    Cause: an issue during the web-scraping stage. Fixed as of the 2024-12-25 dataset, but not fixed retroactively.

    Other grocery pricing resources:

    Statcan data on "Monthly average retail prices for selected products"

  • Manners and Customs of Women

    This is a collection of ukio-e prints from the Royal Ontario Museum. It’s called “Album of prints from Manners and Customs of Women” (Fujin fūzoku zukushi 婦人風俗尽).

    • Artist: Ogata Gekkō 尾形月耕 (1859 – 1920)
    • Medium: Colour woodblock print
    • Date: c. 1896
    • Period: Meiji period
    • Dimensions: Ht. 35.5 x Wt. 24 cm
    • Object number: 979.138.1
    • Credit Line: Gift of Mrs. A. Ledingham in memory of Miss Martha Julia Cartmell, pioneer missionary to Japan

    My favourite is the image to the right – “a courtesan departs” – but so many of these are fantastic. For more ukio-e prints, go to https://ukiyo-e.org/ and scroll down the page. For more cool objects from the ROM Digital Collection, click here.

    Note from Dec. 8, 2024:
    In many Japanese prints of courtesans / “pretty women”, the women’s faces are simply drawn while the hair is drawn elaborately. I believe this is telling about the part of the anatomy that men in the 1700s – 1800s cared about. (The prints above aren’t done in that “pinup” style, and that’s a big part of why I like them).

    Here’s a small look at how complex women’s hair styles and accessories could get, from this 1885 book:

    Note from June 6, 2025:
    More hair stuff! “Tose Kamoji Hinagata” hair catalogue by the illustrator Abe Gyokuwanshi. From this eBay listing.

    April 20, 2026:
    The hair updates just keep on coming. An 1886 catalogue of hair styles in the Museum of Fine Art in Houston. Notice how Western these hairstyles are. We’re deeply into the “learn from the West” period in Meiji Japan.

  • A DAB O’ THE PEN


    What’s a dab o’ the pen ? Weel, a dab o’ the pen
    Is a very wee thing as ye surely maun ken ;
    But a deal may be dune to mar or to men’,
    Wi’ a very sma’ dab o’ a very sma’ pen.

    Ye may fasten your friens or embitter your foes,
    Ye may add to your comforts or fill up your woes,
    An’ a word in gude season is better than ten
    That we sometimes let slip wi’ a dab o’ the pen.

    By a dab o’ the pen ye may get a gude wife,
    Or may get ane wha’ll mak’ ye be sick o’ your life ;
    And its better off-han’ in a way ye suld ken
    To say a kind word than to tak’ up a pen.

    Some tak’ up the pen an’ write to a lass,
    And say that a minute they canna’ let pass,
    Withoot dreams o’ their dearie—an’ richt oot comes then,
    A proposal to marry by dab o’ the pen.

    An’ dab comes the pen by return o’ the post,
    She says that in wonder an’ trouble she’s lost,
    Sin’ the day she was born she couldno bide men,
    But noo she’ll be Jamie’s—by a dab o’ the pen.

    From The Printers’ International Specimen Exchange vol. 5 p. 93
  • Cat

    So last Wednesday my wife is minding her business puttering around in the other room and my son comes in the room and I hear her talking in a low voice and after a while she goes HEY and I hear a plate smash and then the furniture sqreeeking and she’s yelling HEY HEY COME HERE YOU LITTLE and I get up from the computer and I’m walking down the hallway and she’s huffing and yelling I GOT YOU NOW YOU LITTLE SHIT and I’m speeding up and he’s yelling SKREEEEEEE but he’s moving really fast but she’s pinning both his hands(?) with one of hers and she’s huffing now and her black hair is plastered to her forehead with sweat but she’s holding on and her eyes are wild and she says she says: I GOT HIM I GOT HIM and would you look at that! it’s not our son it’s one of them cat demons that dress up and sneak up on you and I NEVER even seen one in real life so I go and make a woodcut print of the whole episode so we can remember and laugh about it later when we sit and sip a yuzu lemonade

    This image is from the Royal Ontario Collection, it is called “Usugumo and the Demon Cat” and is from the series “Gekkō’s Miscellany”. I saw it at the Cat exhibition that’s currently on at the museum. Apparently this is a print of a cat demon that tried to impersonate this lady’s assistant, but she caught him.

  • Mobile-Friendly Image Maps

    An Image Map is a way of creating images with clickable areas in HTML. The image below is an example of an Image Map. Hover or click on the text, flower, apple or horsefly to see what I mean:

    Your browser doesn’t support SVG images

    Traditionally, you’d create an image map with a <map> and an <area> tag. But this approach breaks on mobile browsers because it doesn’t adapt to narrower screens.

    This tutorial will show you how to create mobile-friendly image maps using SVG objects, like the one above. If you are on Desktop: go ahead and shrink the window to see how the image above shrinks & the clickable areas remain in their proper places.

    (Note: there is a good online tool that creates SVG image maps, but it only creates rectangles and the UI breaks sometimes).

    Our goal

    Our end goal is be to mark up the image on the left in such a way that it’ll have the 4 clickable areas on the right. We’re aiming to embed this image map on a webpage in a way that works equally well on desktop and mobile.

    We will accomplish this by creating an SVG object that contains both the image, and the clickable areas.

    Step 1: download Inkscape

    Inkscape is a free & open-source illustration package (like Adobe Illustrator). We will use it for creating an SVG file for our Image Map. Download the latest Inkscape here and install it.

    Step 2: import your image

    Launch Inscape and embed your “base image” by clicking File -> Import . Choose to Embed the image on the window that pops up.

    Step 3: mark up the clickable areas

    Use the “Rectangle”, “Ellipse” and “Pen Tool” to mark your intended clickable areas. In the screenshot below, you can see them as 4 green shapes:

    Next, we’re going to make these clickable areas invisible. Skip Step 4 if you want to keep an outline around your clickable areas to make them easy to discover.

    Step 4: remove the stroke colour

    In the “Dialogs” area to the right, choose the Fill and Stroke icon . Then go to Stroke and click the X to remove the stroke from your clickable shapes . If you don’t see the “Dialogs” area, click View -> Show/Hide Dialogs.

    Step 5: remove the background colour

    In the Dialogs, go to the Fill and Stroke icon , then “Fill” and click the solid colour icon . We’re going to set the transparency (“Alpha”, symbolized by the letter “A”) to 1 . That will make it practically invisible, while keeping some colour there – I found that if we set the background to be fully transparent, then the shape stops being clickable.

    Step 6: turn the shapes into hyperlinks

    Here comes the magic: hover over one of your shapes with the mouse. Right click and choose Create anchor (hyperlink). This will turn the shape into a link.

    In the Dialogs, click the “down arrow” at the far right of the list of icons. A big dropdown list will appear. Choose Object Attributes.

    You should see a set of fields like in the screenshot below:

    If you don’t see these fields, try right-clicking on your shape and choosing Link Properties :

    Fill in these specific details for your clickable area:

    HrefDestination URL
    (with https:// or a relative address)
    TargetAlways “_parent”
    TitleText that should appear on mouse-hover

    Repeat this for every clickable shape, setting it’s own unique destination URL.

    Step 7: export as SVG

    Select the entire image and the shapes covering it.
    Go to File -> Export.
    Click the “Selection” tab and check “Export Selected only” to export only the selected area (instead of the entire blank white page on the screen).
    Then choose your file folder and choose “Plain SVG (*.svg)” from the dropdown next to the filename. Do not choose “Inkscape SVG”.

    Step 8: embed the svg file into your webpage

    Upload the .SVG file you saved to your server. Then, on the page where you’d like your Image Map to appear, put the following HTML code:

    <style>
       #svgimagemap {
         max-width: 100%;
       }
    </style>
    
    <object id="svgimagemap" data="path/to-your/svg-file.svg" type="image/svg+xml"></object>

    This code says that your imagemap object should have a maximum width of 100% of the parent element. Meaning: the image + clickable images will shrink to properly fit a mobile viewport.

    (Optional) Step 9: optimize the svg file

    If your SVG file is larger than you’d like, there are a couple of ways to shrink it down:

    1. Make sure that the “base image” you embedded in the SVG has an efficient format. If your original image was a .PNG, then try converting it to .JPG and then embedding it. If your image as a lot contiguous single-colour areas, then try converting it to .GIF before embedding.
    2. Inkscape exports an SVG file that’s human-readable. You can shrink it down by removing a lot of readability enhancing components (like extra whitespaces). Upload your SVG file to SVGviewer.dev to optimize it and get a smaller version of the same file.

    Email me at jacob at this site to point out mistakes / make suggestions / tell me about the Image Maps you created to give me the warm fuzzies!

    Reference notes:
    https://web.archive.org/web/20160319050818/http://www.creativebloq.com/netmag/create-responsive-svg-image-maps-51411831
    https://stackoverflow.com/a/28277021

  • The Trouble With Monsters

    Dear Daughter,

    Last night when you were falling asleep, you asked me: “Daddy, are there monsters in here”.

    I said “No. Monsters are imaginary.”

    But I lied.

    The trouble with monsters is that they’re hard to spot. They don’t advertise that they’re a monster.

    Monsters don’t come with horns on their heads.

    Monsters are just trying to pay the mortgage, trying to drop the kids off at soccer practice, trying to just God Let Me Keep It Together For One More Day, trying to organize the summer school jamboree as part of Parent Council duties.

    But don’t be fooled: they’ll flay the very skin off your back. Turn it into a rustic carpet. Into a lampshade. And then act all coy when faced with what they’ve done. “We didn’t know”, they’ll say, “we were living next to the abbatoir but never looked in on what those people in that building were doing”.

    Don’t believe them, my darling. Don’t let them near your skin.


    Monsters don’t come with long fuzzy tails. Oh no they don’t.

    Monsters will justify monstrous actions by saying you’re not a person. You’re not like them. With their braying, yapping, clicking language – they can’t understand your words so they pretend that you can’t speak. They’ll never listen to the slow songs of our people, our tales of perseverance, stories of loss, the soul of a nation.

    They’re not listening. They can’t hear it. It doesn’t exist.

    Monsters think they’re just doing what they need to get by. But they’ll snatch the milk right from a newborn’s mouth if given the chance.


    No. Monsters don’t come with hard clacking hooves.

    Monsters boggle the mind with nonsense like We Have To Increase ROI by Seven Percent or Else the Q3 Report Will Have a Negative Outlook and We Are Sorry Stephen We Are Aware That You Have Served the Corporation for Twenty Years But Your Position Has Been Eliminated No It Is NOT YOU It Is YOUR POSITION That HAS BEEN ELIMINATED

    But don’t you ever mistake them for oafs, Daughter.

    Monsters are closer to a dog – to a wolf – than they are to you and to me. Monsters will tear the flesh off your bones with those sharp canines, my twelve ounce New York striploin.

    They’ll shred your little feet into glue.

    Pulverize your fine bones into fertilizer.

    Squelch your curious eyes into hot dog paste.

    No. The trouble with monsters is that they don’t come with horns, or tails, or hooves –

    Monsters are not like you and me at all.

  • Mira Calligraphiae Monumenta – high resolution images

    The Mira Calligraphiae Monumenta is a “Model Book Of Calligraphy” created in 1561–1562 by Georg Bocskay – court secretary to the Holy Roman Emperor Ferdinand I. It was illuminated 30 years later by painter Joris Hoefnagel illuminated the book. The result is “… one of the most unusual collaborations between scribe and painter in the history of manuscript illumination.”

    The Getty Museum Collection digitized the book and made it available online – but their viewer app is restrictive. I’ve made it simpler to view & download below. Note that clicking an image below will bring up a detailed 13Mb version of it. The work is in the public domain – so you can do anything you want with it.

    You can learn more about this book from the Getty Art + Ideas podcast episode about it.