Restricting display of ads by taxonomy terms

g10tto - November 24, 2008 - 18:33
Project:Advertisement
Version:6.x-2.1-rc1
Component:ad_channel module
Category:feature request
Priority:normal
Assigned:tetramentis
Status:needs work
Description

Is it possible?

I have my site divided into different age groups, with stories and ads pertaining to each.

Can I restrict ads to only appear when a user visits a certain story for that age group?

#1

Jeremy - November 25, 2008 - 12:18
Category:task» support request
Status:active» fixed

Please review INSTALL.txt and README.txt that comes with the module. You can create ad groups that match your age groups, which should accomplish your requirements. (Note that the 6.x version of this module is not yet fully completed, however, so you could run into bugs.)

#2

g10tto - November 25, 2008 - 17:16

Here is my setup:

Three ad sizes in three different blocks on the page. The placement of these do not change throughout the site, and there will always be an ad that appears in each.

Currently, the only ad groups are defined as these three positions (Banner, Sidebar, Footer).

Using Taxonomy, I divided my site's stories into 7 "age groups" (Maternity, Baby, Toddler, Child, etc.). Those age groups have subgroups relating to topics such as Health, Development, and School.

Stories are placed into these subgroups - e.g. "Healthy Afterschool Snacks" is located under Child > Health.

So I'd like to have ads that rotate within the main age groups, so that we can target our visitor who may be reading this article with an ad for Juicy Juice or clothing for young children.

I've been able to create the groups and subgroups as a new vocabulary set, but have yet to be able to restrict ads to these groups. Instead, they appear in their regular positions, rotating without specification.

Since taking your suggestion and using Taxonomy to create new ad groups, I find that the ads have only been recreated as new ad blocks, which are not actually controlled by the module's nesting terms.

Each ad should be targeted to its proper age group and only shown as the visitor navigates to different parts of the site.

-------

I know this is perhaps a lot to take in, but I thank you for your help and will continue to search for a solution.

#3

sersim - November 28, 2008 - 15:02

I too would like to have this feature in the ad module.
I thought that the feature "display ads based on node ids (nids), or taxonomy terms (categories)" meant what you are asking for, but maybe I was wrong.

However I found a way:
- install the pathauto module;
- go to Administer › Site building › URL aliases › Automated alias settings and enter a default path pattern for nodes (i.e. [termpath-raw]/[title-raw]) and taxonomy terms (i.e. [vocab-raw]/[catpath-raw])
- create ad groups like Baby-Banner, Baby-Sidebar, etc.
- set the new blocks to be displayed only in the corresponding pages, i.e. baby/*

I hope this helps.

It would be nice to have this feature inside the ad module, so we could not have to use pathauto and we could set an ad to be displayed for nodes with a specific tag too, or for nodes with a particular content type.

#4

System Message - December 12, 2008 - 15:12
Status:fixed» closed

Automatically closed -- issue fixed for two weeks with no activity.

#5

NimrodYonatanBenNes - April 1, 2009 - 13:11

I find the solution of sersim a little cumbersome and not realistic.

If I got many taxonomies categories ("baby" at sersim example), it actually mean that I'll need to create for each Taxonomy category of my site 3 corresponding ad groups (for 3 different locations and banner sizes), I'll also need to associate each banner to lots of groups during the creation if I want a specific banner to be displayed across my site.

There isn't any way to call for an ad with the ad function (or whatever other dynamic way :)) in a format which state the ad group id I want and the term id of the site category that I want? (for example the 'baby' category got term id of 20 and the ad group 'wide banners' got id of 30 I'll just call the ad function like ad(20, 1, 30)).

If this feature doesn't exist how can it be implemented otherwise?

Thanks

#6

NimrodYonatanBenNes - April 1, 2009 - 12:32
Version:6.x-1.x-dev» 6.x-2.0-beta5
Status:closed» active

forgot to reopen :)

** and noticed that it was for the 6.x-1 and not 6.x-2 version... oops... sorry :)

#7

NimrodYonatanBenNes - April 2, 2009 - 10:30

I found that I can make such a functionality by editing the adserve.inc file and adcache.inc
@ adserve.inc I changed line 96 to:
$variables->tids = isset($values['t']) ? preg_replace('/[^0-9,.]/', '', $values['t']) : ''; // just added the '.' string as an approved value
@ adcache.inc I edited line 221 to:
if (ereg('.', $id)) {
$tids = explode('.', $id);

$result = db_query("SELECT a.aid FROM ads a INNER JOIN term_node n ON a.aid = n.nid INNER JOIN term_node z ON a.aid = z.nid
WHERE a.adstatus = 'active' AND n.tid = %d AND z.tid = %d", $tids);
} else {
$result = db_query("SELECT a.aid FROM {ads} a INNER JOIN {term_node} n ON a.aid = n.nid WHERE a.adstatus = 'active' AND n.tid IN(%d)", $id);
}

Those changes allow me to use the ad function like this: ad('21.11', 1) which returned for display only banners which are located in an ad group with id of 21 and also in one of my ordinary site categories with id of 11.

Now I know that my hacks are "ugly" and I'm not even sure if what I did doesn't damage any other functionality (I guess it is), how can I make a decent patch out of this?

Cheers!

#8

NimrodYonatanBenNes - April 10, 2009 - 14:08
Title:Taxonomy to restrict ads to story tags» Restricting display of ads by group ad & site category
Category:support request» feature request

Bumping it up again with little fixes... would love to know how this feature could be implemented

#9

Jeremy - April 14, 2009 - 14:24
Status:active» postponed (maintainer needs more info)

I confess, it's still not clear to me what exactly you are trying to do. Please provide a very simple explanation. Try, for example, to explain what you're aiming for using two example adds "Foo" and "Bar". What groups are each in? How then are you trying to decide which pages they display on?

(Have you tried ad_channels -- they allow you to control which page an advertisement displays on based on path, though it's not clear to me whether or not this is what you're trying to do.)

#10

NimrodYonatanBenNes - April 15, 2009 - 16:55

I rechecked ad_channels to be sure and it give a solution to my issue which is not practical to a site with lots of categories (taxonomies).

I'll try to explain my issue better now (sorry but as u can plainly see I'm not a native English speaker :)).

My site got various categories (taxonomy values) for various content sections (display articles, service providers of the field, etc..), for example:
* Sport
* Health
* Life

Each page at the site got 3 constant areas for displaying image banners, each area display banners of different size then the rest of the areas, for example:
* Top Area - 234px X 90px
* Right Area - 210px X 60px
* Bottom Area - 150px X 60px

For each image banners area I created a group ad (total 3 group ads for the entire site).

And now to my issue... :)

I want to be able to assign each banner that I create to one of the groups ad & also assign it to one or more of my site categories (taxonomy values).
So for example when a user will surf at the "Health" category he will see only banners that are associated to that specific category.

The embedding of the banner should consist of both the ad group id and the taxonomy id (tid), for example: print ad(5, 1, array('tids' => '76')); will display banners which r associated to group id 5 and also to tid 76.

I hope that I was clearer now :)

#11

NimrodYonatanBenNes - April 15, 2009 - 16:57
Version:6.x-2.0-beta5» 6.x-2.0-beta6
Status:postponed (maintainer needs more info)» active

#12

Jeremy - April 15, 2009 - 17:59

Okay, I see what you're trying to do now.

The way I would implement this is in ad_channels. I would add a new "Taxonomy rules" section on the channel configuration page which would allow you to select one or more terms. You could then chose to only display advertisements in this channel to nodes that are in the selected terms. I think this would be a useful feature, and will leave the issue in an active status. Patches welcome!

#13

Jeremy - April 15, 2009 - 18:17
Status:active» postponed

Hm, the challenging part of this will be figuring out what taxonomy a given node is assigned to. We either have to cache this for all nodes (which could take a lot of memory on a large website), or we have to query the database each time we serve an advertisement (which would be very slow). I don't know an ideal way to solve this at the moment... unless you change the paths of your content for each taxonomy type, then you can use the existing code to match based on path.

Due to the potential memory and/or performance issues that this would cause, it's unlikely that I'll implement this.

#14

NimrodYonatanBenNes - April 16, 2009 - 09:31
Status:postponed» active

How about just creating an embedding option only without setting elaborate admin features?

For example: print ad(null, 1, array('tids' => '5, 76')); will run the current query which is located at adcache.inc line 221 but with a slight modification so the result for the above command will result in an sql query like the following:
"SELECT DISTINCT a.aid FROM {ads} a INNER JOIN {term_node} n ON a.aid = n.nid WHERE a.adstatus = 'active' AND n.tid IN(5, 76)" (I just added the DISTINCT and made the IN get multiple values).

Will that be a problem to the module?

#15

Jeremy - April 16, 2009 - 11:55
Status:active» postponed

Any feature affecting ad serving needs to also be implemented in the caching layer -- this means, the functionality needs to be implemented in a way that does not require the database layer. If your site gets much traffic, the module simply won't perform well enough without a cache.

Moving issue into a pending state, which means it's waiting on a comprehensive patch or funding.

#16

tetramentis - October 1, 2009 - 23:37
Version:6.x-2.0-beta6» 6.x-2.1-rc1

I'm also highly interested in being able to display ads by taxonomy terms.

My guess is that "node-to-term" mappings could be cached on cron runs - this seems to be a solution to performance concerns. It could even be cached as an include'able PHP file with a single $array - this would allow server-side PHP caching software (like xcache) to keep that mapping in-RAM between requests. With chmod 600, caching a single variable to a PHP file shouldn't be too much of a security issue.

It also appears that http://drupal.org/node/419196 is related: if a channel is enhanced with "PHP field returns true" filter, then it would be relatively easy to put into that field term_id-checking code, and thus implement "ads by taxonomy terms" using existing 'ad channels' infrastructure.

I'll post back as soon as I'm done following your discussion in the actual module code. In the meantime, any further hints and suggestions would be highly appreciated, as I'm not really familiar with Drupal module development. Also, it would be beneficial to understand Jeremy's vision of the best approach to implement "ads by taxonomy".

#17

tetramentis - October 1, 2009 - 23:51

This one http://drupal.org/node/581450 is also related.

#18

tetramentis - October 6, 2009 - 12:36
Title:Restricting display of ads by group ad & site category» Restricting display of ads by taxonomy terms
Component:ad module» ad_channel module
Status:postponed» needs work

I decided to implement the "terms selection" in channels admin, and not a "PHP field returns true" - largely for ease of use considerations (as Ad module is often used by end-users).

At the moment, I only managed to make the term selects display in a proper fieldset on channel admin page.

The following steps yet have to be performed (any help and hints would be appreciated):
- "Settings" page of the Ad module need a new fieldset "Allowed vocabularies for channels". It should list all the site's vocabularies, and allow checking which of the vocabularies will be used for term selection on the channel admin page. Reason for this fieldset: taxonomy is often used for multiple purposes within a single site, and it is not always necessary to show "ads by taxonomy" on all vocabularies (some of the vocabularies are better hidden than visible). As a more specific example: "ad groups" are implemented as taxonomy, and are already present on the channel admin page, so it's better to hide that vocabulary. Also, consider a website with forum...
- the fieldset I added needs actual code to save the terms selection
- ad_channel.inc needs code to filter display by taxonomy terms
- adache.inc needs code to work around the issues mentioned by Jeremy

Does anybody know if (and how) it is possible to add this functionality by an external module (or a sub-module)? A documentation link would be welcome.

#19

tetramentis - October 6, 2009 - 12:37
Assigned to:Anonymous» tetramentis

#20

tetramentis - October 16, 2009 - 10:06

I'm done with the admin part - added a new fieldset "Allowed vocabularies for channels" to Channels->Settings, and a new fieldset "Taxonomy rules" to Channel edit form. This part is fully functional now.

Getting to the actual filtering now. Will first implement non-cached filtering.

I would still appreciate information on adding my changes as a sub-module to Ad module - if my final solution won't be accepted by Jeremy into the ad_channel module. I've looked through a number of infos, but still do not quite understand how do I modify a form in ad_channel module from a new submodule:
http://groups.drupal.org/node/21725
http://drupal.org/node/508
http://drupal.org/node/206753
http://drupal.org/node/22573

Also, it's not clear if 3rd-level submodules are possible (e.g. ad_channel_taxonomy).

#21

tetramentis - October 16, 2009 - 10:24

patch

it incorporates my fix for http://drupal.org/node/606244

AttachmentSize
ad_channel.patch 5.99 KB

#22

tetramentis - October 19, 2009 - 20:20

Well, I did it. A kind of.

Let me count the number (and type) of MySQL queries added per single call of adserve.php:

  1. one call with JOINs, using taxonomy_node_get_terms() with a fake node object (to avoid loading the node)
  2. one simple call (using variable_get()) to retrieve vocabularies allowed for taxonomy filtering
  3. now the worst part: foreach(ad), foreach(channel) - one call to variable_get(), until some channel matches or there are no more channels

Provided MySQL has a large enough queries_cache configured, I believe all these extra queries will be very fast (on the order of 0.0005 sec on a common quadcore - tested in the non-related scenario with a query returning 66k items, 5-30KiB each).

I didn't really understand how caching is supposed to work here; all the changes were done to ad_channel.inc - which seems to have no caching for URL-based filtering as well. Or is all the caching hidden under $channels = adserve_cache('get_cache', 'channel');? If yes, then I believe #3 from the list of extra queries above could be incorporated into adcache.inc. If yes, #2 could also be cached.

Finally, the firstmost query could be cached to a PHP file, as I suggested earlier. It would be wise to regenerate that cache only on node updates (I believe "Drupal actions" could help here, but I do not know for sure). Of course, that will be a specific caching - I'm not going to dump full node->taxonomy objects.

Any comments/suggestions are welcome.

Jeremy, could you please comment on your willingness to accept this functionality into the Ad module?

#23

Jeremy - October 21, 2009 - 02:08

Thanks for the patch. Some feedback after a quick read through:

  1. Why are you storing this information in a variable instead of in the ad_channel table? I don't see any advantage to this, and believe this data should be moved into the ad_channel table.
  2. Your fake node object will mean that node revisions can't be used. This needs to be fixed. (If you're concerned about node_load performance on your website, try something like this patch: http://tag1consulting.com/patches/load_cache)
  3. I only see a patch for the admin side of things. Did you forget to attach the patch for the rest of the code?
  4. The taxonomy data will need to be cached in ad_channel_ad_build_cache() in ad_channel.module. This cache data then must be used in ad_channel_cache_filter() in ad_channel.inc. You can not make ANY db_query calls in ad_channel.inc, as Drupal will not be bootstrapped if you are using the ad file cache or the ad memcache cache.
  5. Your patch, #606244: Invalid argument supplied for foreach() in includes/form.inc on line 1205, was already committed, it should not be part of this patch.

I will take another look when the above are fixed. You're very much headed in the right direction, thanks for the contribution!

#24

tetramentis - October 21, 2009 - 16:02
  1. That was done solely for the speed of development. I agree this should go into ad_channel table; will do that as time permits
  2. Yes, I understand the revisions issue. Thank you for the link (wow, that's a big list of patches you have there!), but I'm trying to not modify Drupal's core at all. I'll try to implement in-module caching (that just wasn't a priority, yet).
  3. Sorry, not yet used to contributing - patch attached.
  4. Thanks for details on this one, I'll look into that.
  5. Ok (I haven't used git's cherry-picking yet, guess its time to learn it)
AttachmentSize
ad_channel_inc_2.patch 4.36 KB

#25

Jeremy - October 21, 2009 - 16:50

> That was done solely for the speed of development. I agree this should go into
> ad_channel table; will do that as time permits

It will be necessary before this patch will be merged.

> Yes, I understand the revisions issue. Thank you for the link (wow, that's a big list of patches
> you have there!), but I'm trying to not modify Drupal's core at all. I'll try to implement
> in-module caching (that just wasn't a priority, yet).

I would not worry about caching node_load calls -- that's outside the scope of what you're trying to do here. Besides, it's already solved when you enable the ad file cache or memcache-based cache.

I've not yet had a chance to look at your newly attached code, but suspect it needs to be modified anyway to work with the ad caches based on previous comments.

 
 

Drupal is a registered trademark of Dries Buytaert.