#how can show data of User as advertisement ?

127 messages · Page 1 of 1 (latest)

serene pagoda
#

I am trying to show data as advertisement of User from Mongodb database to Next.js 14. I used client side to rotate ads in queue but its not real time.

sleek torrentBOT
#

🔎 This post has been indexed in our web forum and will be seen by search engines so other users can find it outside Discord

🕵️ Your user profile is private by default and won't be visible to users outside Discord, if you want to be visible in the web forum you can add the "Public Profile" role in id:customize

✅ You can mark a message as the answer for your post with Right click -> Apps -> Mark Solution
(if you don't see the option, try refreshing Discord with Ctrl + R)

serene pagoda
#

can anyone help me ?

#

@digital saddle

serene pagoda
#

@snow salmon can you help me

willow saffron
#

first of all don't ping users that are not part of topic.
second of all your explanation of your problem is awfull.
add details, what ads, how it shown now, how it should be, any reference to thing that you want to achieve etc...

serene pagoda
# willow saffron first of all don't ping users that are not part of topic. second of all your exp...
#

User is adding his details and his referral link, I will show their referrals in queue as advertisement

#

I tried with useEffect, but its client side fetching and its not real time, I want all advertisement in sync with all users

willow saffron
#

in your code you are not doing anything with your response, why then you even fetch it?
your pusher looks ok, do you get any messages at all through it? did you check is it work at all?

serene pagoda
serene pagoda
#

I mean this , api/advertisement/getAllAds

#

Its printing all this values from env, so issue is not here
appId: process.env.PUSHER_APP_ID!,
key: process.env.PUSHER_KEY!,
secret: process.env.PUSHER_SECRET!,
cluster: process.env.PUSHER_CLUSTER!,
useTLS: true

willow saffron
#

pusher should have some kind of event logging, also you can add console.log to emitters and subscriptions to check are they working

serene pagoda
# willow saffron pusher should have some kind of event logging, also you can add console.log to e...

error :

Ad rotation triggered: Response {type: 'basic', url: 'http://localhost:3000/api/advertisement/getAllAds', redirected: false, status: 405, ok: false, …} ....
....................

for Adbox component :

  useEffect(() => {

    fetch('/api/advertisement/getAllAds').then(response => {
      console.log('Ad rotation triggered:', response);
    }).catch(error => {
      console.error('Error triggering ad rotation:', error);
    });


    console.log('Adbox pusher api start')
    const pusher = new Pusher(process.env.NEXT_PUBLIC_PUSHER_KEY!, {
      cluster: process.env.NEXT_PUBLIC_PUSHER_CLUSTER!,
      forceTLS: true
    });

    console.log('Adbox pusher api middle')
    const channel = pusher.subscribe('ad-channel');
    channel.bind('ad-update', function(data:any) {
      console.log('Received ad update:', data); // Check the data received
      setCurrentAd(data.ad);
    });
  
    return () => {
      pusher.unsubscribe('ad-channel');
      channel.unbind_all();
    };
    
  }, []);
#

For currentAd state :
console.log error : Adbox pusher: null

#

my issue is I know how to fetch data through route in Next.js but unable to do with pusher

#

Is my tech stack right ?
I mean pusher for real time data, I mean to fetch

willow saffron
serene pagoda
#

gone

#

now its 500

#

error

willow saffron
#

check server logs

serene pagoda
#

wait bro

#

what do yo mean ?

👇👇
also, from where this url triggers? if from some external source it will not have access to your localhost:3000 ?

willow saffron
#

I don't know where you call it, is it some webhook url, or is it some url that you call in your code.

willow saffron
#

right now you need to check your pusher account and it should have some kind of logs

serene pagoda
# willow saffron right now you need to check your pusher account and it should have some kind of ...

logs in server side of Next.js

null
 ⨯ node_modules\pusher\lib\errors.js (13:0) @ new RequestErrorunhandledRejection: Error
    at new RequestError (webpack-internal:///(rsc)/./node_modules/pusher/lib/errors.js:13:16)        
    at eval (webpack-internal:///(rsc)/./node_modules/pusher/lib/requests.js:61:17)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Timeout.eval [as _onTimeout] (webpack-internal:///(rsc)/./app/api/advertisement/getAllAds/route.ts:31:13) {
  name: 'PusherRequestError',
  message: 'Unexpected status code 413',
  url: 'https://api-ap2.pusher.com/apps/1791291/events?auth_key=1124eb29e2343d430175&auth_timestamp=1714565710&auth_version=1.0&body_md5=9407ca774dc5539f5b0730b8a1dd27c2&auth_signature=d050297c957aeb4b2617ab130c8c74a0b4e380a73d39baf7a859b8404405380d',
  error: undefined,
  status: 413,
  body: 'The data content of this event exceeds the allowed maximum (10240 bytes). See https://pusher.com/docs/channels/server_api/http-api#publishing-events for more info\n'
}
willow saffron
#

The data content of this event exceeds the allowed maximum (10240 bytes)

#

they allow only short messagees 10kb

serene pagoda
#

My request method was GET, why its showing POST

#

this errors are from pusher server logs

willow saffron
willow saffron
# serene pagoda can you explain this

it's self explanatory,
you are calling

await pusher.trigger('ad-channel', 'ad-update', {
          ad
        });

which call POST request to pusher API, which show you error that your message bigger than allowed in API limits.

serene pagoda
#

now I am getting response but not image

serene pagoda
#

but I want images also

willow saffron
serene pagoda
#

I am getting data from backend

 export async function GET(req: Request) {
    try {
      await connectDB();
      const ads = await Advertisement.find({});


      console.log('ads through pusher:', ads)
willow saffron
#

you sent a lot of data, I am saying send only update event

await pusher.trigger('ad-channel', 'ad-update', {upd:1});
willow saffron
#

small update event

serene pagoda
#

my code is :

await pusher.trigger('ad-channel', 'ad-update', {
   ad
});
willow saffron
#

when you get such small update event

#

you refetching data from your api

serene pagoda
serene pagoda
willow saffron
#

which giant object that rejected by pusher because of size

serene pagoda
willow saffron
#

so instead you send small message

#

upd is short for update

#

you can send whatever you want

#

it just should be small

serene pagoda
willow saffron
#

yes

serene pagoda
#

not got this, for currentAd state

Adbox pusher: undefined
import React, { useEffect, useState } from 'react';
import Pusher from 'pusher-js';
import Image from 'next/image';

type AdType = {
    _id: string;
    link: string;
    image: string;
}

const AdBox = () => {
  const [currentAd, setCurrentAd] = useState<AdType | null>(null);

  useEffect(() => {

    fetch('/api/advertisement/getAllAds').then(response => {
      console.log('Ad rotation triggered:', response);
    }).catch(error => {
      console.error('Error triggering ad rotation:', error);
    });

    const pusher = new Pusher(process.env.NEXT_PUBLIC_PUSHER_KEY!, {
      cluster: process.env.NEXT_PUBLIC_PUSHER_CLUSTER!,
      forceTLS: true
    });

    console.log('Adbox pusher api middle')
    const channel = pusher.subscribe('ad-channel');
    channel.bind('ad-update', function(data:any) {
      console.log('Received ad update:', data); // Check the data received
      setCurrentAd(data.ad);
    });
    
    return () => {
      pusher.unsubscribe('ad-channel');
      channel.unbind_all();
    };
  
  console.log('Adbox pusher:', currentAd)
  return (
    <div>
      {currentAd && (
        <div>
          <Image src={currentAd.image} alt="Advertisement" width={300} height={300} layout="responsive" />
          <a href={currentAd.link} target="_blank" rel="noopener noreferrer">Visit Ad</a>
        </div>
      )}
    </div>
  );
};

export default AdBox;
#

for

Received ad update: {upd: 1}
willow saffron
#

if it's message from console then you get update
now you need to change

 channel.bind('ad-update', function(data:any) {
      console.log('Received ad update:', data); // Check the data received
      setCurrentAd(data.ad);
    });

so it refetch data

fetch('/api/advertisement/getAllAds').then(response => {
      console.log('Ad rotation triggered:', response);
    }).catch(error => {
      console.error('Error triggering ad rotation:', error);
    });

and set it to your state

serene pagoda
#

I added ad to pass object through response
route.ts

export async function GET(req: Request) {
    try {
      await connectDB();
      const ads = await Advertisement.find({});


      console.log('ads through pusher:', ads)

      let currentAdIndex = 0;
      setInterval(async () => {
        
        const ad = ads[currentAdIndex];
        console.log(`Sending ad: ${currentAdIndex}`, ad);
        await pusher.trigger('ad-channel', 'ad-update', {
          upd: 1
        });
        currentAdIndex = (currentAdIndex + 1) % ads.length;
      }, 20000);

      return NextResponse.json({ message: 'Ad rotation started', ad: ads[currentAdIndex] });
    } catch (error) {
      console.error('Error rotating ads:', error);
    }
}
#

its only trigger event, which is pusher.trigger

not fetching data, I mean get request after each trigger

#

and now its only getting undefined for
Ad rotation ads in json

willow saffron
serene pagoda
#
const fetchAds = async() => {
    try{
      const response = await axios.get('/api/advertisement/getAllAds');
      console.log('response', response?.data)
      setCurrentAd(response?.data?.ad)
    }catch(error){
      console.log('Error fetching ads:', error);
    }
  }

useEffect(() => {
    fetchAds();

    const pusher = new Pusher(process.env.NEXT_PUBLIC_PUSHER_KEY!, {
      cluster: process.env.NEXT_PUBLIC_PUSHER_CLUSTER!,
      forceTLS: true
    });

    const channel = pusher.subscribe('ad-channel');
    channel.bind('ad-update', function(data:any) {
      console.log('Received ad update:', data); 
      fetchAds();
    });
    
    return () => {
      pusher.unsubscribe('ad-channel');
      channel.unbind_all();
    };
        
  }, []);

#

I changed method from fetch to async await and invoke in useEffect first then also in bind method (fetchAds())

willow saffron
serene pagoda
#

I will show you

willow saffron
#

based on that you receive a lot ad-update update events, then you probably generating a lot of them

serene pagoda
#

changes I made is added state isFetch and use it in useEffect for if condition of fetchAds invoking

const AdBox = () => {
  const [currentAd, setCurrentAd] = useState<AdType | null>(null);
  const [isFetch, setIsFetch] = useState<boolean>(true);

  const fetchAds = async() => {
    try{
      const response = await axios.get('/api/advertisement/getAllAds');
      setCurrentAd(response?.data?.ad)
    }catch(error){
      console.log('Error fetching ads:', error);
    }
  }

  useEffect(() => {
    if(isFetch){
      fetchAds();
      setIsFetch(false);
    }
    
    const pusher = new Pusher(process.env.NEXT_PUBLIC_PUSHER_KEY!, {
      cluster: process.env.NEXT_PUBLIC_PUSHER_CLUSTER!,
      forceTLS: true
    });

    const channel = pusher.subscribe('ad-channel');
    channel.bind('ad-update', function(data:any) {
      console.log('Received ad update:', data); // Check the data received
      fetchAds();
    });
    
    return () => {
      pusher.unsubscribe('ad-channel');
      channel.unbind_all();
    };
        
  }, []);
  
  console.log('Adbox pusher:', currentAd)
  return (.....
    )
}
serene pagoda
#

Is here I making any mistake, in pusher.trigger?

export async function GET(req: Request) {
    try {
      await connectDB();
      const ads = await Advertisement.find({});

      console.log('ads through pusher:', ads)

      let currentAdIndex = 0;
      setInterval(async () => {
        
        const ad = ads[currentAdIndex];
        console.log(`Sending ad: ${currentAdIndex}`, ad);
        await pusher.trigger('ad-channel', 'ad-update', {
          upd: 1
        });
        currentAdIndex = (currentAdIndex + 1) % ads.length;
      }, 60000);

      console.log('ad res:', ads[currentAdIndex])

      return NextResponse.json({ message: 'Ad rotation started', ad: ads[currentAdIndex] });
    } catch (error) {
      console.error('Error rotating ads:', error);
    }
}
willow saffron
willow saffron
#

why?

serene pagoda
#

I want to invoke data from ad array in queue, like google ads, each object contain link and image, that I want to show on frontend

willow saffron
#

you need to stop your deployment of site because it basically generates thousands of events right now

serene pagoda
#

don't worry

willow saffron
#

wdym? if you receiveing events then pusher works

#

and eventually it will start charge money

serene pagoda
willow saffron
#

you generating thousands of events through pusher right now

serene pagoda
#

oh

#

yes

willow saffron
#

you don't need setinterval, you need to trigger single update event. that's all
after that your client will fetch all new data from server

serene pagoda
#

but how it fetch after each 1 minute

willow saffron
#

you have code

channel.bind('ad-update', function(data:any) {
      console.log('Received ad update:', data); // Check the data received
      fetchAds();
    });

that will fetch it as soon as receiveing upd signal

#

right now you sending thousands signals and it making thousands fetches

serene pagoda
#

it triggers new request, that I understand but what about timing

willow saffron
#

why 1 minute? from where this 1 minute arise? you wanted update your ad in real time, your code without setinterval will update it in real time

serene pagoda
willow saffron
#

why?

serene pagoda
#

ok, I will explain you

#

I have users data, we can consider 1000 users

#

and they submit their site link and image or anything they want to promote

#

and its in database and I am rendering those data as advertisemnet on frontend

#

if there 1000 Users,
each User's advertisement will run for 1 minute, after that advertisement will change and next User's advertisement will show .

I can change time from 1 minute to 2 minutes.

#

I use real time cause I want to show advertisement in sync, like A user will see 'xy' advertisement then B user will see same advertsement.

I tried this with client side fetching with only useEffect but it fetches from 1st each time if I open app and If I close it starts from 1st again. So its not syncing real time, right ?

#

this feature I want to implement

#

bro, have you got my point ?

#

for reference this is document data

willow saffron
#

I will not help you with implementation, you have no idea what you working with, you need to read how giant ads networks work, and gain more experience in programming.
I can give you direction, if you want to be in sync you can use user UTC as point in sync, because it will be same for everyone. and setInterval should be run on client. Using websocket for this task is useless waste of resources, especially for syncing.

serene pagoda
#

bro, pls help me, I already waited for so long. No one knows,
atleast now its working

serene pagoda
#

and for senterval, I can remove it from server side, get data in array of 10 list items, then can show on client side with setinterval

#

is that ok ?

#

or should I use other option like redis, can I do that with redis ?

willow saffron
#

UTC will give you data in sync, as I said it same for everyone, deviation is insignificant for human eye.
redis or memcached is required.
but your "auction" of banners is bad, your clients will waste their money with such calculations, you need ton of additional logging for fair views calculation. it's not a single pusher websocket task, it's much more because people pay for view.

serene pagoda
#

like this

const updateCurrentAd = (ads: AdType[]) => {
        const minutes = new Date().getUTCMinutes();
        const currentAdIndex = minutes % ads.length;
        setCurrentAd(ads[currentAdIndex]);
    };
#
const AdBox = () => {
    const [ads, setAds] = useState<AdType[]>([]);
    const [currentAd, setCurrentAd] = useState<AdType | null>(null);

    const fetchAds = async () => {
        try {
            const response = await axios.get('/api/advertisement/getAllAds');
            setAds(response.data.ads);
            updateCurrentAd(response.data.ads);
        } catch (error) {
            console.error('Error fetching ads:', error);
        }
    };

    const updateCurrentAd = (ads: AdType[]) => {
        const minutes = new Date().getUTCMinutes();
        const currentAdIndex = minutes % ads.length;
        setCurrentAd(ads[currentAdIndex]);
    };

    useEffect(() => {
        fetchAds();
        const interval = setInterval(() => {
            if (ads.length > 0) {
                updateCurrentAd(ads);
            }
        }, 1000 * 10); // check every 10 seconds to limit checks

        return () => clearInterval(interval);
    }, [ads]);
willow saffron
#

something like that is minimal setup, but this still not include view amount, because each and every network and device is different it can take like 20s to fetch new data, so you need a lot of additional counter when image change, when it's loaded in DOM, how many user saw it etc......
you need to have your action alghoritm, what if new ad arrived, what if some was deleted etc......
it's freaking rabbit hole.

serene pagoda
#

if its possible on client side with UTC, I will try that.

#

I just want ads in syncronize for all users